mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-11 13:04:05 +01:00
Mechanical Ploughs
- Added the Mechanical Plough - Mounted Drills now briefly stall a contraption after breaking a block below falling blocks (sand, gravel, etc) - Mechanical Saws can now harvest Bamboo, Chorus, Kelp, Sugar Cane, Cactus, Melons and Pumpkins - Fixed harvester position inconsistency when moved vertically - Fixed saws/drills not hurting entities in some cases - Fixed saws/drill throwing back hurt entities in weird directions
This commit is contained in:
parent
83cfc097ae
commit
45897e4c18
@ -14,6 +14,7 @@ import com.simibubi.create.modules.IModule;
|
||||
import com.simibubi.create.modules.contraptions.CasingBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.actors.DrillBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.actors.HarvesterBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.actors.PloughBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.actors.PortableStorageInterfaceBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.clock.CuckooClockBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.ClockworkBearingBlock;
|
||||
@ -162,9 +163,10 @@ public enum AllBlocks {
|
||||
ROTATION_CHASSIS(new RadialChassisBlock()),
|
||||
DRILL(new DrillBlock()),
|
||||
SAW(new SawBlock()),
|
||||
HARVESTER(new HarvesterBlock()),
|
||||
DEPLOYER(new DeployerBlock()),
|
||||
PORTABLE_STORAGE_INTERFACE(new PortableStorageInterfaceBlock()),
|
||||
PLOUGH(new PloughBlock()),
|
||||
HARVESTER(new HarvesterBlock()),
|
||||
ANALOG_LEVER(new AnalogLeverBlock()),
|
||||
|
||||
ANDESITE_CASING(new CasingBlock("andesite_casing")),
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.simibubi.create.foundation.utility;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -8,8 +9,16 @@ import java.util.Set;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import net.minecraft.block.BambooBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.CactusBlock;
|
||||
import net.minecraft.block.ChorusFlowerBlock;
|
||||
import net.minecraft.block.ChorusPlantBlock;
|
||||
import net.minecraft.block.KelpBlock;
|
||||
import net.minecraft.block.KelpTopBlock;
|
||||
import net.minecraft.block.LeavesBlock;
|
||||
import net.minecraft.block.SugarCaneBlock;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@ -40,6 +49,41 @@ public class TreeCutter {
|
||||
Set<BlockPos> visited = new HashSet<>();
|
||||
List<BlockPos> frontier = new LinkedList<>();
|
||||
|
||||
// Bamboo, Sugar Cane, Cactus
|
||||
BlockState stateAbove = reader.getBlockState(pos.up());
|
||||
if (isVerticalPlant(stateAbove)) {
|
||||
logs.add(pos.up());
|
||||
for (int i = 1; i < 256; i++) {
|
||||
BlockPos current = pos.up(i);
|
||||
if (!isVerticalPlant(reader.getBlockState(current)))
|
||||
break;
|
||||
logs.add(current);
|
||||
}
|
||||
Collections.reverse(logs);
|
||||
return new Tree(logs, leaves);
|
||||
}
|
||||
|
||||
// Chorus
|
||||
if (isChorus(stateAbove)) {
|
||||
frontier.add(pos.up());
|
||||
while (!frontier.isEmpty()) {
|
||||
BlockPos current = frontier.remove(0);
|
||||
visited.add(current);
|
||||
logs.add(current);
|
||||
for (Direction direction : Iterate.directions) {
|
||||
BlockPos offset = current.offset(direction);
|
||||
if (visited.contains(offset))
|
||||
continue;
|
||||
if (!isChorus(reader.getBlockState(offset)))
|
||||
continue;
|
||||
frontier.add(offset);
|
||||
}
|
||||
}
|
||||
Collections.reverse(logs);
|
||||
return new Tree(logs, leaves);
|
||||
}
|
||||
|
||||
// Regular Tree
|
||||
if (!validateCut(reader, pos))
|
||||
return null;
|
||||
|
||||
@ -94,6 +138,25 @@ public class TreeCutter {
|
||||
return new Tree(logs, leaves);
|
||||
}
|
||||
|
||||
public static boolean isChorus(BlockState stateAbove) {
|
||||
return stateAbove.getBlock() instanceof ChorusPlantBlock || stateAbove.getBlock() instanceof ChorusFlowerBlock;
|
||||
}
|
||||
|
||||
public static boolean isVerticalPlant(BlockState stateAbove) {
|
||||
Block block = stateAbove.getBlock();
|
||||
if (block instanceof BambooBlock)
|
||||
return true;
|
||||
if (block instanceof CactusBlock)
|
||||
return true;
|
||||
if (block instanceof SugarCaneBlock)
|
||||
return true;
|
||||
if (block instanceof KelpBlock)
|
||||
return true;
|
||||
if (block instanceof KelpTopBlock)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a tree was fully cut by seeing whether the layer above the cut
|
||||
* is not supported by any more logs.
|
||||
|
@ -0,0 +1,60 @@
|
||||
package com.simibubi.create.modules.contraptions.components.actors;
|
||||
|
||||
import com.simibubi.create.foundation.utility.AllShapes;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.HorizontalBlock;
|
||||
import net.minecraft.item.BlockItemUseContext;
|
||||
import net.minecraft.state.StateContainer.Builder;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
|
||||
public abstract class AttachedActorBlock extends HorizontalBlock implements IPortableBlock {
|
||||
|
||||
public AttachedActorBlock() {
|
||||
super(Properties.from(Blocks.IRON_BLOCK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||
Direction direction = state.get(HORIZONTAL_FACING);
|
||||
return AllShapes.HARVESTER_BASE.get(direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer(Builder<Block, BlockState> builder) {
|
||||
builder.add(HORIZONTAL_FACING);
|
||||
super.fillStateContainer(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
|
||||
Direction direction = state.get(HORIZONTAL_FACING);
|
||||
BlockPos offset = pos.offset(direction.getOpposite());
|
||||
return Block.hasSolidSide(worldIn.getBlockState(offset), worldIn, offset, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||
Direction facing;
|
||||
if (context.getFace().getAxis().isVertical())
|
||||
facing = context.getPlacementHorizontalFacing().getOpposite();
|
||||
else {
|
||||
BlockState blockState =
|
||||
context.getWorld().getBlockState(context.getPos().offset(context.getFace().getOpposite()));
|
||||
if (blockState.getBlock() instanceof AttachedActorBlock)
|
||||
facing = blockState.get(HORIZONTAL_FACING);
|
||||
else
|
||||
facing = context.getFace();
|
||||
}
|
||||
return getDefaultState().with(HORIZONTAL_FACING, facing);
|
||||
}
|
||||
|
||||
}
|
@ -6,9 +6,11 @@ import com.simibubi.create.modules.contraptions.components.contraptions.Movement
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FallingBlock;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.util.DamageSource;
|
||||
@ -32,30 +34,10 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
|
||||
World world = context.world;
|
||||
BlockState stateVisited = world.getBlockState(pos);
|
||||
|
||||
if (!stateVisited.isNormalCube(world, pos))
|
||||
damageEntities(context, pos, world);
|
||||
if (world.isRemote)
|
||||
return;
|
||||
if (stateVisited.getCollisionShape(world, pos).isEmpty()) {
|
||||
DamageSource damageSource = getDamageSource();
|
||||
if (damageSource == null)
|
||||
return;
|
||||
for (Entity entity : world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(pos))) {
|
||||
|
||||
if (entity instanceof ItemEntity)
|
||||
return;
|
||||
if (entity instanceof ContraptionEntity)
|
||||
return;
|
||||
if (entity instanceof AbstractMinecartEntity)
|
||||
for (Entity passenger : entity.getRecursivePassengers())
|
||||
if (passenger instanceof ContraptionEntity
|
||||
&& ((ContraptionEntity) passenger).getContraption() == context.contraption)
|
||||
return;
|
||||
|
||||
float damage = (float) MathHelper.clamp(Math.abs(context.relativeMotion.length() * 10) + 1, 5, 20);
|
||||
entity.attackEntityFrom(damageSource, damage);
|
||||
entity.setMotion(entity.getMotion().add(context.relativeMotion.scale(3)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!canBreak(world, pos, stateVisited))
|
||||
return;
|
||||
|
||||
@ -63,10 +45,39 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
|
||||
context.stall = true;
|
||||
}
|
||||
|
||||
public void damageEntities(MovementContext context, BlockPos pos, World world) {
|
||||
DamageSource damageSource = getDamageSource();
|
||||
if (damageSource == null && !throwsEntities())
|
||||
return;
|
||||
Entities: for (Entity entity : world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(pos))) {
|
||||
if (entity instanceof ItemEntity)
|
||||
continue;
|
||||
if (entity instanceof ContraptionEntity)
|
||||
continue;
|
||||
if (entity instanceof AbstractMinecartEntity)
|
||||
for (Entity passenger : entity.getRecursivePassengers())
|
||||
if (passenger instanceof ContraptionEntity
|
||||
&& ((ContraptionEntity) passenger).getContraption() == context.contraption)
|
||||
continue Entities;
|
||||
|
||||
float damage = (float) MathHelper.clamp(Math.abs(context.relativeMotion.length() * 10) + 1, 5, 20);
|
||||
if (damageSource != null && !world.isRemote)
|
||||
entity.attackEntityFrom(damageSource, damage);
|
||||
if (throwsEntities() && (world.isRemote == (entity instanceof PlayerEntity))) {
|
||||
entity.setMotion(entity.getMotion().add(context.motion.add(0, context.motion.length() / 4f, 0)));
|
||||
entity.velocityChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected DamageSource getDamageSource() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean throwsEntities() {
|
||||
return getDamageSource() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopMoving(MovementContext context) {
|
||||
CompoundNBT data = context.data;
|
||||
@ -89,6 +100,27 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
|
||||
|
||||
@Override
|
||||
public void tick(MovementContext context) {
|
||||
tickBreaker(context);
|
||||
|
||||
CompoundNBT data = context.data;
|
||||
if (!data.contains("WaitingTicks"))
|
||||
return;
|
||||
|
||||
int waitingTicks = data.getInt("WaitingTicks");
|
||||
if (waitingTicks-- > 0) {
|
||||
data.putInt("WaitingTicks", waitingTicks);
|
||||
context.stall = true;
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos pos = NBTUtil.readBlockPos(data.getCompound("LastPos"));
|
||||
data.remove("WaitingTicks");
|
||||
data.remove("LastPos");
|
||||
context.stall = false;
|
||||
visitNewPosition(context, pos);
|
||||
}
|
||||
|
||||
public void tickBreaker(MovementContext context) {
|
||||
CompoundNBT data = context.data;
|
||||
if (context.world.isRemote)
|
||||
return;
|
||||
@ -129,13 +161,13 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
|
||||
|
||||
if (destroyProgress >= 10) {
|
||||
BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack));
|
||||
onBlockBroken(context, breakingPos);
|
||||
context.stall = false;
|
||||
onBlockBroken(context, breakingPos, stateToBreak);
|
||||
ticksUntilNextProgress = -1;
|
||||
world.sendBlockBreakProgress(id, breakingPos, -1);
|
||||
data.remove("Progress");
|
||||
data.remove("TicksUntilNextProgress");
|
||||
data.remove("BreakingPos");
|
||||
context.stall = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -150,7 +182,15 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
|
||||
return BlockBreakingKineticTileEntity.isBreakable(state, blockHardness);
|
||||
}
|
||||
|
||||
protected void onBlockBroken(MovementContext context, BlockPos pos) {
|
||||
protected void onBlockBroken(MovementContext context, BlockPos pos, BlockState brokenState) {
|
||||
BlockState above = context.world.getBlockState(pos.up());
|
||||
if (!(above.getBlock() instanceof FallingBlock))
|
||||
return;
|
||||
|
||||
CompoundNBT data = context.data;
|
||||
data.putInt("WaitingTicks", 10);
|
||||
data.put("LastPos", NBTUtil.writeBlockPos(pos));
|
||||
context.stall = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,8 +4,11 @@ import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
@ -27,10 +30,15 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||
public SuperByteBuffer renderInContraption(MovementContext context) {
|
||||
return DrillTileEntityRenderer.renderInContraption(context);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected DamageSource getDamageSource() {
|
||||
return DrillBlock.damageSourceDrill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
|
||||
return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos).isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,34 +1,17 @@
|
||||
package com.simibubi.create.modules.contraptions.components.actors;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.foundation.utility.AllShapes;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.HorizontalBlock;
|
||||
import net.minecraft.block.material.PushReaction;
|
||||
import net.minecraft.item.BlockItemUseContext;
|
||||
import net.minecraft.state.StateContainer.Builder;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
|
||||
public class HarvesterBlock extends HorizontalBlock implements IPortableBlock {
|
||||
public class HarvesterBlock extends AttachedActorBlock implements IPortableBlock {
|
||||
|
||||
public static MovementBehaviour MOVEMENT = new HarvesterMovementBehaviour();
|
||||
|
||||
public HarvesterBlock() {
|
||||
super(Properties.from(Blocks.IRON_BLOCK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTileEntity(BlockState state) {
|
||||
return true;
|
||||
@ -39,51 +22,11 @@ public class HarvesterBlock extends HorizontalBlock implements IPortableBlock {
|
||||
return new HarvesterTileEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PushReaction getPushReaction(BlockState state) {
|
||||
return PushReaction.PUSH_ONLY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||
Direction direction = state.get(HORIZONTAL_FACING);
|
||||
return AllShapes.HARVESTER_BASE.get(direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillStateContainer(Builder<Block, BlockState> builder) {
|
||||
builder.add(HORIZONTAL_FACING);
|
||||
super.fillStateContainer(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockRenderLayer getRenderLayer() {
|
||||
return BlockRenderLayer.CUTOUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
|
||||
Direction direction = state.get(HORIZONTAL_FACING);
|
||||
BlockPos offset = pos.offset(direction.getOpposite());
|
||||
return Block.hasSolidSide(worldIn.getBlockState(offset), worldIn, offset, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||
Direction facing;
|
||||
if (context.getFace().getAxis().isVertical())
|
||||
facing = context.getPlacementHorizontalFacing().getOpposite();
|
||||
else {
|
||||
BlockState blockState =
|
||||
context.getWorld().getBlockState(context.getPos().offset(context.getFace().getOpposite()));
|
||||
if (AllBlocks.HARVESTER.typeOf(blockState))
|
||||
facing = blockState.get(HORIZONTAL_FACING);
|
||||
else
|
||||
facing = context.getFace();
|
||||
}
|
||||
return getDefaultState().with(HORIZONTAL_FACING, facing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovementBehaviour getMovementBehaviour() {
|
||||
return MOVEMENT;
|
||||
|
@ -42,7 +42,7 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
|
||||
|
||||
@Override
|
||||
public Vec3d getActiveAreaOffset(MovementContext context) {
|
||||
return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.5);
|
||||
return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.45);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,34 @@
|
||||
package com.simibubi.create.modules.contraptions.components.actors;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
|
||||
public class PloughBlock extends AttachedActorBlock {
|
||||
|
||||
public static MovementBehaviour MOVEMENT = new PloughMovementBehaviour();
|
||||
|
||||
@Override
|
||||
public MovementBehaviour getMovementBehaviour() {
|
||||
return MOVEMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* The OnHoeUse event takes a player, so we better not pass null
|
||||
*/
|
||||
static class PloughFakePlayer extends FakePlayer {
|
||||
|
||||
public static final GameProfile PLOUGH_PROFILE =
|
||||
new GameProfile(UUID.fromString("9e2faded-eeee-4ec2-c314-dad129ae971d"), "Plough");
|
||||
|
||||
public PloughFakePlayer(ServerWorld world) {
|
||||
super(world, PLOUGH_PROFILE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package com.simibubi.create.modules.contraptions.components.actors;
|
||||
|
||||
import static net.minecraft.block.HorizontalBlock.HORIZONTAL_FACING;
|
||||
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.modules.contraptions.components.actors.PloughBlock.PloughFakePlayer;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemUseContext;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.RayTraceContext;
|
||||
import net.minecraft.util.math.RayTraceContext.BlockMode;
|
||||
import net.minecraft.util.math.RayTraceContext.FluidMode;
|
||||
import net.minecraft.util.math.RayTraceResult.Type;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||
|
||||
@Override
|
||||
public boolean isActive(MovementContext context) {
|
||||
return !VecHelper.isVecPointingTowards(context.relativeMotion,
|
||||
context.state.get(HORIZONTAL_FACING).getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||
super.visitNewPosition(context, pos);
|
||||
|
||||
World world = context.world;
|
||||
if (world.isRemote)
|
||||
return;
|
||||
BlockPos below = pos.down();
|
||||
if (!world.isBlockPresent(below))
|
||||
return;
|
||||
|
||||
Vec3d vec = VecHelper.getCenterOf(pos);
|
||||
PloughFakePlayer player = getPlayer(context);
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
BlockRayTraceResult ray = world
|
||||
.rayTraceBlocks(new RayTraceContext(vec, vec.add(0, -1, 0), BlockMode.OUTLINE, FluidMode.NONE, player));
|
||||
if (ray == null || ray.getType() != Type.BLOCK)
|
||||
return;
|
||||
|
||||
ItemUseContext ctx = new ItemUseContext(player, Hand.MAIN_HAND, ray);
|
||||
new ItemStack(Items.DIAMOND_HOE).onItemUse(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3d getActiveAreaOffset(MovementContext context) {
|
||||
return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.45);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean throwsEntities() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
|
||||
return state.getCollisionShape(world, breakingPos).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopMoving(MovementContext context) {
|
||||
if (context.temporaryData instanceof PloughFakePlayer)
|
||||
((PloughFakePlayer) context.temporaryData).remove();
|
||||
}
|
||||
|
||||
private PloughFakePlayer getPlayer(MovementContext context) {
|
||||
if (!(context.temporaryData instanceof PloughFakePlayer) && context.world instanceof ServerWorld) {
|
||||
PloughFakePlayer player = new PloughFakePlayer((ServerWorld) context.world);
|
||||
player.setHeldItem(Hand.MAIN_HAND, new ItemStack(Items.DIAMOND_HOE));
|
||||
context.temporaryData = player;
|
||||
}
|
||||
return (PloughFakePlayer) context.temporaryData;
|
||||
}
|
||||
|
||||
}
|
@ -6,6 +6,7 @@ import com.simibubi.create.foundation.utility.TreeCutter.Tree;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||
import com.simibubi.create.modules.contraptions.components.saw.SawBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.saw.SawTileEntity;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
@ -31,12 +32,13 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||
|
||||
@Override
|
||||
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
|
||||
return super.canBreak(world, breakingPos, state)
|
||||
&& (state.isIn(BlockTags.LOGS) || state.isIn(BlockTags.LEAVES));
|
||||
return super.canBreak(world, breakingPos, state) && SawTileEntity.isSawable(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBlockBroken(MovementContext context, BlockPos pos) {
|
||||
protected void onBlockBroken(MovementContext context, BlockPos pos, BlockState brokenState) {
|
||||
if (brokenState.isIn(BlockTags.LEAVES))
|
||||
return;
|
||||
Tree tree = TreeCutter.cutTree(context.world, pos);
|
||||
if (tree != null) {
|
||||
for (BlockPos log : tree.logs)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.simibubi.create.modules.contraptions.components.contraptions;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.modules.contraptions.components.actors.AttachedActorBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.actors.HarvesterBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.actors.PortableStorageInterfaceBlock;
|
||||
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.ClockworkBearingBlock;
|
||||
@ -175,7 +176,7 @@ public class BlockMovementTraits {
|
||||
return direction == (state.get(BlockStateProperties.HANGING) ? Direction.UP : Direction.DOWN);
|
||||
if (block instanceof AbstractRailBlock)
|
||||
return direction == Direction.DOWN;
|
||||
if (block instanceof HarvesterBlock)
|
||||
if (block instanceof AttachedActorBlock)
|
||||
return direction == state.get(HarvesterBlock.HORIZONTAL_FACING).getOpposite();
|
||||
return false;
|
||||
}
|
||||
@ -191,7 +192,7 @@ public class BlockMovementTraits {
|
||||
return state.get(BlockStateProperties.FACING) == facing;
|
||||
if (AllBlocks.PORTABLE_STORAGE_INTERFACE.typeOf(state))
|
||||
return state.get(PortableStorageInterfaceBlock.FACING) == facing;
|
||||
if (AllBlocks.HARVESTER.typeOf(state))
|
||||
if (state.getBlock() instanceof AttachedActorBlock)
|
||||
return state.get(BlockStateProperties.HORIZONTAL_FACING) == facing;
|
||||
if (AllBlocks.ROPE_PULLEY.typeOf(state))
|
||||
return facing == Direction.DOWN;
|
||||
|
@ -24,7 +24,15 @@ import com.simibubi.create.modules.contraptions.components.actors.BlockBreakingK
|
||||
import com.simibubi.create.modules.contraptions.processing.ProcessingInventory;
|
||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
|
||||
|
||||
import net.minecraft.block.BambooBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.CactusBlock;
|
||||
import net.minecraft.block.ChorusPlantBlock;
|
||||
import net.minecraft.block.KelpBlock;
|
||||
import net.minecraft.block.KelpTopBlock;
|
||||
import net.minecraft.block.StemGrownBlock;
|
||||
import net.minecraft.block.SugarCaneBlock;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@ -379,7 +387,29 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity {
|
||||
|
||||
@Override
|
||||
public boolean canBreak(BlockState stateToBreak, float blockHardness) {
|
||||
return super.canBreak(stateToBreak, blockHardness) && stateToBreak.isIn(BlockTags.LOGS);
|
||||
boolean sawable = isSawable(stateToBreak);
|
||||
return super.canBreak(stateToBreak, blockHardness) && sawable;
|
||||
}
|
||||
|
||||
public static boolean isSawable(BlockState stateToBreak) {
|
||||
if (stateToBreak.isIn(BlockTags.LOGS) || stateToBreak.isIn(BlockTags.LEAVES))
|
||||
return true;
|
||||
Block block = stateToBreak.getBlock();
|
||||
if (block instanceof BambooBlock)
|
||||
return true;
|
||||
if (block instanceof StemGrownBlock)
|
||||
return true;
|
||||
if (block instanceof CactusBlock)
|
||||
return true;
|
||||
if (block instanceof SugarCaneBlock)
|
||||
return true;
|
||||
if (block instanceof KelpBlock)
|
||||
return true;
|
||||
if (block instanceof KelpTopBlock)
|
||||
return true;
|
||||
if (block instanceof ChorusPlantBlock)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
14
src/main/resources/assets/create/blockstates/plough.json
Normal file
14
src/main/resources/assets/create/blockstates/plough.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"forge_marker": 1,
|
||||
"defaults": {
|
||||
"model": "create:block/plough"
|
||||
},
|
||||
"variants": {
|
||||
"facing": {
|
||||
"north": { "y": 180 },
|
||||
"south": {},
|
||||
"east": { "y": 270 },
|
||||
"west": { "y": 90 }
|
||||
}
|
||||
}
|
||||
}
|
@ -99,6 +99,7 @@
|
||||
"block.create.drill": "Mechanical Drill",
|
||||
"block.create.portable_storage_interface": "Portable Storage Interface",
|
||||
"block.create.harvester": "Mechanical Harvester",
|
||||
"block.create.plough": "Mechanical Plough",
|
||||
"block.create.saw": "Mechanical Saw",
|
||||
"block.create.water_wheel": "Water Wheel",
|
||||
"block.create.mechanical_press": "Mechanical Press",
|
||||
@ -986,16 +987,21 @@
|
||||
"block.create.rotation_chassis.tooltip.action1": "Makes the clicked face _Sticky_. When Chassis move, all designated blocks attached to the sticky side are moved with it.",
|
||||
|
||||
"block.create.drill.tooltip": "MECHANICAL DRILL",
|
||||
"block.create.drill.tooltip.summary": "A mechanical device suitable for _breaking_ _blocks_. It is movable with _Mechanical_ _Pistons_ or _Bearings_.",
|
||||
"block.create.drill.tooltip.summary": "A mechanical device suitable for _breaking_ _blocks_. It is movable with _Mechanical_ _Pistons_, _Bearings_ or other controllers.",
|
||||
"block.create.drill.tooltip.condition1": "When Rotated",
|
||||
"block.create.drill.tooltip.behaviour1": "Acts as a _stationary_ Block Breaker. Also _hurts_ _entities_ in its effective area.",
|
||||
"block.create.drill.tooltip.condition2": "While Moving",
|
||||
"block.create.drill.tooltip.behaviour2": "Breaks Blocks with which the drill collides.",
|
||||
|
||||
"block.create.harvester.tooltip": "MECHANICAL HARVESTER",
|
||||
"block.create.harvester.tooltip.summary": "A mechanical plant cutter suitable for medium scale crop automation. It is movable with _Mechanical_ _Pistons_ or _Bearings_.",
|
||||
"block.create.harvester.tooltip.summary": "A mechanical plant cutter suitable for medium scale crop automation. It is movable with _Mechanical_ _Pistons_, _Bearings_ or other controllers.",
|
||||
"block.create.harvester.tooltip.condition1": "While Moving",
|
||||
"block.create.harvester.tooltip.behaviour1": "_Harvests_ all _mature_ _crops_ which which the blade collides and reset them to their initial growth state.",
|
||||
|
||||
"block.create.plough.tooltip": "MECHANICAL PLOUGH",
|
||||
"block.create.plough.tooltip.summary": "A mechanical plough has a variety of uses. It is movable with _Mechanical_ _Pistons_, _Bearings_ or other controllers.",
|
||||
"block.create.plough.tooltip.condition1": "While Moving",
|
||||
"block.create.plough.tooltip.behaviour1": "_Breaks_ _blocks_ which _cannot_ _be_ _collided_ with, such as torches, tracks or snow layers. _Applies_ its _motion_ to _entities_ without hurting them. _Tills_ _soil_ _blocks_ as though a Hoe would be used on them.",
|
||||
|
||||
"block.create.saw.tooltip": "MECHANICAL SAW",
|
||||
"block.create.saw.tooltip.summary": "Suitable for _cutting_ _trees_ effectively and for _cutting_ _blocks_ into their carpentered counterparts. It is movable using _Mechanical_ _Pistons_ or _Bearings_.",
|
||||
@ -1025,7 +1031,7 @@
|
||||
"block.create.redstone_bridge.tooltip.action2": "Toggles between _Receiver_ and _Transmitter_ Mode.",
|
||||
|
||||
"block.create.contact.tooltip": "REDSTONE CONTACT",
|
||||
"block.create.contact.tooltip.summary": "Only emits redstone power in pairs. It is movable with _Mechanical_ _Pistons_ or _Bearings_.",
|
||||
"block.create.contact.tooltip.summary": "Only emits redstone power in pairs. It is movable with _Mechanical_ _Pistons_, _Bearings_ or other controllers.",
|
||||
"block.create.contact.tooltip.condition1": "When facing other Contact",
|
||||
"block.create.contact.tooltip.behaviour1": "Provides a _Redstone_ _Signal_.",
|
||||
"block.create.contact.tooltip.condition2": "While Moving",
|
||||
|
113
src/main/resources/assets/create/models/block/plough.json
Normal file
113
src/main/resources/assets/create/models/block/plough.json
Normal file
@ -0,0 +1,113 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"textures": {
|
||||
"1": "block/anvil",
|
||||
"particle": "create:block/andesite_casing_short",
|
||||
"andesite_casing_short": "create:block/andesite_casing_short"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "Core",
|
||||
"from": [0, 2, 0],
|
||||
"to": [16, 14, 2.9],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 4, 16, 16], "texture": "#andesite_casing_short"},
|
||||
"east": {"uv": [2, 0, 14, 3], "rotation": 270, "texture": "#andesite_casing_short"},
|
||||
"south": {"uv": [0, 4, 16, 16], "texture": "#andesite_casing_short"},
|
||||
"west": {"uv": [2, 0, 14, 3], "rotation": 90, "texture": "#andesite_casing_short"},
|
||||
"up": {"uv": [0, 0, 16, 2.9], "rotation": 180, "texture": "#andesite_casing_short"},
|
||||
"down": {"uv": [0, 0, 16, 2.9], "texture": "#andesite_casing_short"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Attachment",
|
||||
"from": [0.1, 4, 6],
|
||||
"to": [2, 7, 15],
|
||||
"rotation": {"angle": 22.5, "axis": "x", "origin": [0, 10, 3]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 1.9, 3], "texture": "#andesite_casing_short"},
|
||||
"east": {"uv": [0, 0, 9, 3], "texture": "#andesite_casing_short"},
|
||||
"south": {"uv": [0.1, 8, 2, 11], "texture": "#andesite_casing_short"},
|
||||
"west": {"uv": [0, 0, 9, 3], "texture": "#andesite_casing_short"},
|
||||
"up": {"uv": [0, 4, 1.9, 13], "texture": "#andesite_casing_short"},
|
||||
"down": {"uv": [0, 4, 1.9, 13], "texture": "#andesite_casing_short"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Attachment",
|
||||
"from": [2.1, 5, 5],
|
||||
"to": [14, 6, 17],
|
||||
"rotation": {"angle": 22.5, "axis": "x", "origin": [0, 10, 3]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 11.9, 1], "texture": "#andesite_casing_short"},
|
||||
"east": {"uv": [0, 0, 12, 1], "texture": "#1"},
|
||||
"south": {"uv": [2, 15, 13.9, 16], "texture": "#1"},
|
||||
"west": {"uv": [0, 0, 12, 1], "texture": "#1"},
|
||||
"up": {"uv": [2, 2, 13.9, 14], "texture": "#1"},
|
||||
"down": {"uv": [2, 4, 13.9, 16], "texture": "#1"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Attachment",
|
||||
"from": [14, 4, 6],
|
||||
"to": [15.9, 7, 15],
|
||||
"rotation": {"angle": 22.5, "axis": "x", "origin": [0, 10, 3]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 1.9, 3], "texture": "#andesite_casing_short"},
|
||||
"east": {"uv": [0, 0, 9, 3], "texture": "#andesite_casing_short"},
|
||||
"south": {"uv": [14, 8, 15.9, 11], "texture": "#andesite_casing_short"},
|
||||
"west": {"uv": [0, 0, 9, 3], "texture": "#andesite_casing_short"},
|
||||
"up": {"uv": [14, 4, 15.9, 13], "texture": "#andesite_casing_short"},
|
||||
"down": {"uv": [14, 4, 15.9, 13], "texture": "#andesite_casing_short"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Attachment",
|
||||
"from": [0, 4, 2.9],
|
||||
"to": [16, 7, 6],
|
||||
"rotation": {"angle": 0, "axis": "x", "origin": [0, 10, 2]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 16, 3], "texture": "#andesite_casing_short"},
|
||||
"east": {"uv": [0, 0, 3.1, 3], "texture": "#andesite_casing_short"},
|
||||
"south": {"uv": [0, 0, 16, 3], "texture": "#andesite_casing_short"},
|
||||
"west": {"uv": [0, 0, 3.1, 3], "texture": "#andesite_casing_short"},
|
||||
"up": {"uv": [0, 0, 16, 3], "rotation": 180, "texture": "#andesite_casing_short"},
|
||||
"down": {"uv": [0, 0, 16, 3], "texture": "#andesite_casing_short"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [75, -135, 0],
|
||||
"translation": [0, 2.5, 0],
|
||||
"scale": [0.375, 0.375, 0.375]
|
||||
},
|
||||
"thirdperson_lefthand": {
|
||||
"rotation": [75, -135, 0],
|
||||
"translation": [0, 2.5, 0],
|
||||
"scale": [0.375, 0.375, 0.375]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [0, -135, 0],
|
||||
"scale": [0.4, 0.4, 0.4]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [0, 225, 0],
|
||||
"scale": [0.4, 0.4, 0.4]
|
||||
},
|
||||
"ground": {
|
||||
"translation": [0, 3, 0],
|
||||
"scale": [0.25, 0.25, 0.25]
|
||||
},
|
||||
"gui": {
|
||||
"rotation": [30, 45, 0],
|
||||
"translation": [1, 0, 0],
|
||||
"scale": [0.625, 0.625, 0.625]
|
||||
},
|
||||
"fixed": {
|
||||
"rotation": [0, 180, 0],
|
||||
"translation": [0, 0, -4],
|
||||
"scale": [0.5, 0.5, 0.5]
|
||||
}
|
||||
}
|
||||
}
|
3
src/main/resources/assets/create/models/item/plough.json
Normal file
3
src/main/resources/assets/create/models/item/plough.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "create:block/plough"
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "create:plough"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
{
|
||||
"type": "crafting_shaped",
|
||||
"pattern": [
|
||||
"III",
|
||||
"AAA",
|
||||
" C "
|
||||
],
|
||||
"key": {
|
||||
"C": {
|
||||
"item": "create:andesite_casing"
|
||||
},
|
||||
"I": {
|
||||
"tag": "forge:plates/iron"
|
||||
},
|
||||
"A": {
|
||||
"item": "create:andesite_alloy"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "create:plough",
|
||||
"count": 1
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"type": "create:module",
|
||||
"module": "contraptions"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user