Playtest Issues, Part II

- Fixed some harvesting problems with custom tools, adresses #91
- Made Shaft placement less retarded
- Fixed blockstate rotation for directional blocks with two orientations per direction
- Harvesters now break sugar cane at the position they are at
- Made contact condition for storage interfaces more lenient
- Sideways actors in the center of a bearing contraption no longer get special treatment if their effective position points outward
- Tried to fix fall damage when riding on downward moving contraptions
- Minecart contraptions turn sharper
- Cart assemblers can now assemble even when the minecart has not passed the center yet
- Fixed deployers forgetting about their held item on the client
- Deployers no longer dump their inventory when a contraption disassembles
- Deployers no longer visually spazz out when getting centered bearing treatment
- Transposers and Extractors now always stall the belt when not able to extract from it
- Extractors no longer drop items on belts that aren't moving
- Transposers no longer require a block to sit on
- Transposers can now be flipped using a wrench
This commit is contained in:
simibubi 2020-03-14 13:36:24 +01:00
parent 73f41ccce8
commit 2f5d2adc9f
18 changed files with 252 additions and 74 deletions

View file

@ -7,13 +7,16 @@ import static com.simibubi.create.foundation.item.AllToolTypes.SHOVEL;
import static com.simibubi.create.foundation.item.AllToolTypes.SWORD; import static com.simibubi.create.foundation.item.AllToolTypes.SWORD;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.simibubi.create.foundation.packet.SimplePacketBase; import com.simibubi.create.foundation.packet.SimplePacketBase;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.Enchantment;
@ -25,6 +28,7 @@ import net.minecraft.item.Items;
import net.minecraft.item.ToolItem; import net.minecraft.item.ToolItem;
import net.minecraft.nbt.NBTUtil; import net.minecraft.nbt.NBTUtil;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
@ -41,7 +45,7 @@ public abstract class AbstractToolItem extends ToolItem {
public AbstractToolItem(float attackDamageIn, float attackSpeedIn, IItemTier tier, Properties builder, public AbstractToolItem(float attackDamageIn, float attackSpeedIn, IItemTier tier, Properties builder,
AllToolTypes... types) { AllToolTypes... types) {
super(attackDamageIn, attackSpeedIn, tier, Collections.emptySet(), setToolTypes(builder, tier, types)); super(attackDamageIn, attackSpeedIn, tier, getEffectiveBlocks(types), setToolTypes(builder, tier, types));
toolTypes = types; toolTypes = types;
} }
@ -76,6 +80,32 @@ public abstract class AbstractToolItem extends ToolItem {
return canEnchant; return canEnchant;
} }
private static Set<Block> getEffectiveBlocks(AllToolTypes... types) {
Set<Block> blocks = new HashSet<>();
for (AllToolTypes type : types) {
switch (type) {
case AXE:
blocks.addAll(EffectiveBlocks.AXE);
break;
case HOE:
break;
case PICKAXE:
blocks.addAll(EffectiveBlocks.PICKAXE);
break;
case SHEARS:
break;
case SHOVEL:
blocks.addAll(EffectiveBlocks.SHOVEL);
break;
case SWORD:
break;
default:
break;
}
}
return blocks;
}
private static Properties setToolTypes(Properties builder, IItemTier tier, AllToolTypes... types) { private static Properties setToolTypes(Properties builder, IItemTier tier, AllToolTypes... types) {
for (AllToolTypes type : types) { for (AllToolTypes type : types) {
if (type == PICKAXE) if (type == PICKAXE)
@ -106,8 +136,21 @@ public abstract class AbstractToolItem extends ToolItem {
@Override @Override
public boolean canHarvestBlock(ItemStack stack, BlockState state) { public boolean canHarvestBlock(ItemStack stack, BlockState state) {
return super.canHarvestBlock(stack, state) || getToolTypes(stack).contains(state.getHarvestTool()) int i = this.getTier().getHarvestLevel();
|| hasType(SWORD) && Items.WOODEN_SWORD.canHarvestBlock(stack, state); if (getToolTypes(stack).contains(state.getHarvestTool()))
return i >= state.getHarvestLevel();
Material material = state.getMaterial();
boolean canHarvestMaterial = false;
if (hasType(PICKAXE))
canHarvestMaterial |= material == Material.ROCK || material == Material.IRON || material == Material.ANVIL;
if (hasType(SHOVEL))
canHarvestMaterial |= Items.WOODEN_SHOVEL.canHarvestBlock(stack, state);
if (hasType(SWORD))
canHarvestMaterial |= Items.WOODEN_SWORD.canHarvestBlock(stack, state);
if (hasType(AllToolTypes.SHEARS))
canHarvestMaterial |= Items.SHEARS.canHarvestBlock(state);
return canHarvestMaterial;
} }
@Override @Override
@ -117,8 +160,16 @@ public abstract class AbstractToolItem extends ToolItem {
@Override @Override
public float getDestroySpeed(ItemStack stack, BlockState state) { public float getDestroySpeed(ItemStack stack, BlockState state) {
if (hasType(SWORD)) Material material = state.getMaterial();
return Items.WOODEN_SWORD.getDestroySpeed(stack, state); if (hasType(PICKAXE) && (material == Material.IRON || material == Material.ANVIL || material == Material.ROCK))
return this.efficiency;
if (hasType(AXE) && (material == Material.WOOD || material == Material.PLANTS
|| material == Material.TALL_PLANTS || material == Material.BAMBOO))
return this.efficiency;
if (hasType(SWORD)
&& (state.getBlock() == Blocks.COBWEB || material == Material.PLANTS || material == Material.TALL_PLANTS
|| material == Material.CORAL || state.isIn(BlockTags.LEAVES) || material == Material.GOURD))
return this.efficiency;
return super.getDestroySpeed(stack, state); return super.getDestroySpeed(stack, state);
} }

View file

@ -0,0 +1,67 @@
package com.simibubi.create.foundation.item;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
public class EffectiveBlocks {
static final Set<Block> AXE = Sets.newHashSet(Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS,
Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, Blocks.BOOKSHELF, Blocks.OAK_WOOD,
Blocks.SPRUCE_WOOD, Blocks.BIRCH_WOOD, Blocks.JUNGLE_WOOD, Blocks.ACACIA_WOOD, Blocks.DARK_OAK_WOOD,
Blocks.OAK_LOG, Blocks.SPRUCE_LOG, Blocks.BIRCH_LOG, Blocks.JUNGLE_LOG, Blocks.ACACIA_LOG,
Blocks.DARK_OAK_LOG, Blocks.CHEST, Blocks.PUMPKIN, Blocks.CARVED_PUMPKIN, Blocks.JACK_O_LANTERN,
Blocks.MELON, Blocks.LADDER, Blocks.SCAFFOLDING, Blocks.OAK_BUTTON, Blocks.SPRUCE_BUTTON,
Blocks.BIRCH_BUTTON, Blocks.JUNGLE_BUTTON, Blocks.DARK_OAK_BUTTON, Blocks.ACACIA_BUTTON,
Blocks.OAK_PRESSURE_PLATE, Blocks.SPRUCE_PRESSURE_PLATE, Blocks.BIRCH_PRESSURE_PLATE,
Blocks.JUNGLE_PRESSURE_PLATE, Blocks.DARK_OAK_PRESSURE_PLATE, Blocks.ACACIA_PRESSURE_PLATE);
static final Set<Block> PICKAXE = ImmutableSet.of(Blocks.ACTIVATOR_RAIL, Blocks.COAL_ORE, Blocks.COBBLESTONE,
Blocks.DETECTOR_RAIL, Blocks.DIAMOND_BLOCK, Blocks.DIAMOND_ORE, Blocks.POWERED_RAIL, Blocks.GOLD_BLOCK,
Blocks.GOLD_ORE, Blocks.ICE, Blocks.IRON_BLOCK, Blocks.IRON_ORE, Blocks.LAPIS_BLOCK, Blocks.LAPIS_ORE,
Blocks.MOSSY_COBBLESTONE, Blocks.NETHERRACK, Blocks.PACKED_ICE, Blocks.BLUE_ICE, Blocks.RAIL,
Blocks.REDSTONE_ORE, Blocks.SANDSTONE, Blocks.CHISELED_SANDSTONE, Blocks.CUT_SANDSTONE,
Blocks.CHISELED_RED_SANDSTONE, Blocks.CUT_RED_SANDSTONE, Blocks.RED_SANDSTONE, Blocks.STONE, Blocks.GRANITE,
Blocks.POLISHED_GRANITE, Blocks.DIORITE, Blocks.POLISHED_DIORITE, Blocks.ANDESITE, Blocks.POLISHED_ANDESITE,
Blocks.STONE_SLAB, Blocks.SMOOTH_STONE_SLAB, Blocks.SANDSTONE_SLAB, Blocks.PETRIFIED_OAK_SLAB,
Blocks.COBBLESTONE_SLAB, Blocks.BRICK_SLAB, Blocks.STONE_BRICK_SLAB, Blocks.NETHER_BRICK_SLAB,
Blocks.QUARTZ_SLAB, Blocks.RED_SANDSTONE_SLAB, Blocks.PURPUR_SLAB, Blocks.SMOOTH_QUARTZ,
Blocks.SMOOTH_RED_SANDSTONE, Blocks.SMOOTH_SANDSTONE, Blocks.SMOOTH_STONE, Blocks.STONE_BUTTON,
Blocks.STONE_PRESSURE_PLATE, Blocks.POLISHED_GRANITE_SLAB, Blocks.SMOOTH_RED_SANDSTONE_SLAB,
Blocks.MOSSY_STONE_BRICK_SLAB, Blocks.POLISHED_DIORITE_SLAB, Blocks.MOSSY_COBBLESTONE_SLAB,
Blocks.END_STONE_BRICK_SLAB, Blocks.SMOOTH_SANDSTONE_SLAB, Blocks.SMOOTH_QUARTZ_SLAB, Blocks.GRANITE_SLAB,
Blocks.ANDESITE_SLAB, Blocks.RED_NETHER_BRICK_SLAB, Blocks.POLISHED_ANDESITE_SLAB, Blocks.DIORITE_SLAB,
Blocks.SHULKER_BOX, Blocks.BLACK_SHULKER_BOX, Blocks.BLUE_SHULKER_BOX, Blocks.BROWN_SHULKER_BOX,
Blocks.CYAN_SHULKER_BOX, Blocks.GRAY_SHULKER_BOX, Blocks.GREEN_SHULKER_BOX, Blocks.LIGHT_BLUE_SHULKER_BOX,
Blocks.LIGHT_GRAY_SHULKER_BOX, Blocks.LIME_SHULKER_BOX, Blocks.MAGENTA_SHULKER_BOX,
Blocks.ORANGE_SHULKER_BOX, Blocks.PINK_SHULKER_BOX, Blocks.PURPLE_SHULKER_BOX, Blocks.RED_SHULKER_BOX,
Blocks.WHITE_SHULKER_BOX, Blocks.YELLOW_SHULKER_BOX);
static final Set<Block> SHOVEL = Sets.newHashSet(Blocks.CLAY, Blocks.DIRT, Blocks.COARSE_DIRT, Blocks.PODZOL,
Blocks.FARMLAND, Blocks.GRASS_BLOCK, Blocks.GRAVEL, Blocks.MYCELIUM, Blocks.SAND, Blocks.RED_SAND,
Blocks.SNOW_BLOCK, Blocks.SNOW, Blocks.SOUL_SAND, Blocks.GRASS_PATH, Blocks.WHITE_CONCRETE_POWDER,
Blocks.ORANGE_CONCRETE_POWDER, Blocks.MAGENTA_CONCRETE_POWDER, Blocks.LIGHT_BLUE_CONCRETE_POWDER,
Blocks.YELLOW_CONCRETE_POWDER, Blocks.LIME_CONCRETE_POWDER, Blocks.PINK_CONCRETE_POWDER,
Blocks.GRAY_CONCRETE_POWDER, Blocks.LIGHT_GRAY_CONCRETE_POWDER, Blocks.CYAN_CONCRETE_POWDER,
Blocks.PURPLE_CONCRETE_POWDER, Blocks.BLUE_CONCRETE_POWDER, Blocks.BROWN_CONCRETE_POWDER,
Blocks.GREEN_CONCRETE_POWDER, Blocks.RED_CONCRETE_POWDER, Blocks.BLACK_CONCRETE_POWDER);
static final Set<Block> PATHABLES =
Sets.newHashSet(Blocks.GRASS_BLOCK, Blocks.DIRT, Blocks.COARSE_DIRT, Blocks.PODZOL);
static final Map<Block, Block> BLOCK_STRIPPING_MAP = (new Builder<Block, Block>())
.put(Blocks.OAK_WOOD, Blocks.STRIPPED_OAK_WOOD).put(Blocks.OAK_LOG, Blocks.STRIPPED_OAK_LOG)
.put(Blocks.DARK_OAK_WOOD, Blocks.STRIPPED_DARK_OAK_WOOD)
.put(Blocks.DARK_OAK_LOG, Blocks.STRIPPED_DARK_OAK_LOG).put(Blocks.ACACIA_WOOD, Blocks.STRIPPED_ACACIA_WOOD)
.put(Blocks.ACACIA_LOG, Blocks.STRIPPED_ACACIA_LOG).put(Blocks.BIRCH_WOOD, Blocks.STRIPPED_BIRCH_WOOD)
.put(Blocks.BIRCH_LOG, Blocks.STRIPPED_BIRCH_LOG).put(Blocks.JUNGLE_WOOD, Blocks.STRIPPED_JUNGLE_WOOD)
.put(Blocks.JUNGLE_LOG, Blocks.STRIPPED_JUNGLE_LOG).put(Blocks.SPRUCE_WOOD, Blocks.STRIPPED_SPRUCE_WOOD)
.put(Blocks.SPRUCE_LOG, Blocks.STRIPPED_SPRUCE_LOG).build();
}

View file

@ -8,6 +8,7 @@ import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Rotation;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
@ -111,6 +112,13 @@ public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBloc
return super.getRotationAxis(state); return super.getRotationAxis(state);
} }
@Override
public BlockState rotate(BlockState state, Rotation rot) {
if (rot.ordinal() % 2 == 1)
state = state.cycle(AXIS_ALONG_FIRST_COORDINATE);
return super.rotate(state, rot);
}
@Override @Override
public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) {
return face.getAxis() == getRotationAxis(state); return face.getAxis() == getRotationAxis(state);

View file

@ -68,7 +68,8 @@ public abstract class RotatedPillarKineticBlock extends KineticBlock {
Axis preferredAxis = getPreferredAxis(context); Axis preferredAxis = getPreferredAxis(context);
if (preferredAxis != null && !context.isPlacerSneaking()) if (preferredAxis != null && !context.isPlacerSneaking())
return this.getDefaultState().with(AXIS, preferredAxis); return this.getDefaultState().with(AXIS, preferredAxis);
return this.getDefaultState().with(AXIS, context.getNearestLookingDirection().getAxis()); return this.getDefaultState().with(AXIS,
preferredAxis == null ? context.getFace().getAxis() : context.getNearestLookingDirection().getAxis());
} }
@Override @Override

View file

@ -53,12 +53,6 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
if (world.isRemote) if (world.isRemote)
return; return;
if (stateVisited.getBlock() == Blocks.SUGAR_CANE) {
notCropButCuttable = true;
pos = pos.up();
stateVisited = world.getBlockState(pos);
}
if (!isValidCrop(world, pos, stateVisited)) { if (!isValidCrop(world, pos, stateVisited)) {
if (isValidOther(world, pos, stateVisited)) if (isValidOther(world, pos, stateVisited))
notCropButCuttable = true; notCropButCuttable = true;

View file

@ -32,7 +32,7 @@ public class StorageInterfaceMovement extends MovementBehaviour {
@Override @Override
public Vec3d getActiveAreaOffset(MovementContext context) { public Vec3d getActiveAreaOffset(MovementContext context) {
return new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING).getDirectionVec()).scale(.65f); return new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING).getDirectionVec()).scale(.85f);
} }
@Override @Override

View file

@ -164,7 +164,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
prevYaw = yaw; prevYaw = yaw;
yaw = angleLerp(0.2f, yaw, targetYaw); yaw = angleLerp(0.4f, yaw, targetYaw);
boolean wasStalled = isStalled(); boolean wasStalled = isStalled();
tickActors(movementVector); tickActors(movementVector);
@ -220,6 +220,9 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (getContraption() instanceof BearingContraption) { if (getContraption() instanceof BearingContraption) {
BearingContraption bc = (BearingContraption) getContraption(); BearingContraption bc = (BearingContraption) getContraption();
Direction facing = bc.getFacing(); Direction facing = bc.getFacing();
Vec3d activeAreaOffset = actor.getActiveAreaOffset(context);
if (activeAreaOffset.mul(VecHelper.planeByNormal(new Vec3d(facing.getDirectionVec())))
.equals(Vec3d.ZERO)) {
if (VecHelper.onSameAxis(blockInfo.pos, BlockPos.ZERO, facing.getAxis())) { if (VecHelper.onSameAxis(blockInfo.pos, BlockPos.ZERO, facing.getAxis())) {
context.motion = new Vec3d(facing.getDirectionVec()).scale( context.motion = new Vec3d(facing.getDirectionVec()).scale(
facing.getAxis().getCoordinate(roll - prevRoll, yaw - prevYaw, pitch - prevPitch)); facing.getAxis().getCoordinate(roll - prevRoll, yaw - prevYaw, pitch - prevPitch));
@ -233,6 +236,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
} }
} }
}
} }
context.rotation = rotationVec; context.rotation = rotationVec;
@ -423,6 +428,9 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
public void preventMovedEntitiesFromGettingStuck() { public void preventMovedEntitiesFromGettingStuck() {
Vec3d stuckTest = new Vec3d(0, -2, 0); Vec3d stuckTest = new Vec3d(0, -2, 0);
for (Entity e : collidingEntities) { for (Entity e : collidingEntities) {
e.fallDistance = 0;
e.onGround = true;
Vec3d vec = stuckTest; Vec3d vec = stuckTest;
AxisAlignedBB axisalignedbb = e.getBoundingBox().offset(0, 2, 0); AxisAlignedBB axisalignedbb = e.getBoundingBox().offset(0, 2, 0);
ISelectionContext iselectioncontext = ISelectionContext.forEntity(this); ISelectionContext iselectioncontext = ISelectionContext.forEntity(this);

View file

@ -1,7 +1,11 @@
package com.simibubi.create.modules.contraptions.components.contraptions; package com.simibubi.create.modules.contraptions.components.contraptions;
import static net.minecraft.state.properties.BlockStateProperties.AXIS;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; 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.BeltBlock.Slope;
@ -10,7 +14,6 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.SlabBlock; import net.minecraft.block.SlabBlock;
import net.minecraft.block.StairsBlock; import net.minecraft.block.StairsBlock;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.Half; import net.minecraft.state.properties.Half;
import net.minecraft.state.properties.SlabType; import net.minecraft.state.properties.SlabType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
@ -136,12 +139,16 @@ public class StructureTransform {
return state; return state;
} }
if (state.has(BlockStateProperties.FACING)) { if (state.has(FACING)) {
state = Direction newFacing = transformFacing(state.get(FACING));
state.with(BlockStateProperties.FACING, transformFacing(state.get(BlockStateProperties.FACING))); if (state.has(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE)) {
if (rotationAxis == newFacing.getAxis() && rotation.ordinal() % 2 == 1)
state = state.cycle(DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE);
}
state = state.with(FACING, newFacing);
} else if (state.has(BlockStateProperties.AXIS)) { } else if (state.has(AXIS)) {
state = state.with(BlockStateProperties.AXIS, transformAxis(state.get(BlockStateProperties.AXIS))); state = state.with(AXIS, transformAxis(state.get(AXIS)));
} else if (rotation == Rotation.CLOCKWISE_180) { } else if (rotation == Rotation.CLOCKWISE_180) {
state = state.rotate(rotation); state = state.rotate(rotation);
@ -172,7 +179,7 @@ public class StructureTransform {
if (rotation == Rotation.NONE) if (rotation == Rotation.NONE)
return state; return state;
BlockState rotated = state.with(BlockStateProperties.AXIS, transformAxis(state.get(BlockStateProperties.AXIS))); BlockState rotated = state.with(AXIS, transformAxis(state.get(AXIS)));
AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock(); AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock();
for (Direction face : Direction.values()) { for (Direction face : Direction.values()) {

View file

@ -22,7 +22,6 @@ import net.minecraft.state.properties.RailShape;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.util.math.shapes.VoxelShapes;
@ -63,16 +62,6 @@ public class CartAssemblerBlock extends AbstractRailBlock {
public void onMinecartPass(BlockState state, World world, BlockPos pos, AbstractMinecartEntity cart) { public void onMinecartPass(BlockState state, World world, BlockPos pos, AbstractMinecartEntity cart) {
if (!cart.canBeRidden()) if (!cart.canBeRidden())
return; return;
Vec3d p = cart.getPositionVec();
Vec3d m = cart.getMotion();
Vec3d p2 = p.add(m);
Direction facing = Direction.getFacingFromVector(m.x, m.y, m.z);
Axis axis = facing.getAxis();
double coord = axis.getCoordinate(pos.getX(), pos.getY(), pos.getZ()) + .5 + .25f * facing.getAxisDirection().getOffset();
if ((axis.getCoordinate(p.x, p.y, p.z) > coord) == (axis.getCoordinate(p2.x, p2.y, p2.z) % 1 > coord))
return;
if (state.get(POWERED)) if (state.get(POWERED))
disassemble(world, pos, cart); disassemble(world, pos, cart);
else else

View file

@ -17,6 +17,7 @@ import com.simibubi.create.modules.logistics.item.filter.FilterItem;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.ListNBT;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -89,10 +90,12 @@ public class DeployerMovementBehaviour extends MovementBehaviour {
public void stopMoving(MovementContext context) { public void stopMoving(MovementContext context) {
if (context.world.isRemote) if (context.world.isRemote)
return; return;
tryDisposeOfEverything(context);
DeployerFakePlayer player = getPlayer(context); DeployerFakePlayer player = getPlayer(context);
if (player == null) if (player == null)
return; return;
context.tileData.put("Inventory", player.inventory.write(new ListNBT()));
player.remove(); player.remove();
} }
@ -107,18 +110,6 @@ public class DeployerMovementBehaviour extends MovementBehaviour {
} }
} }
private void tryDisposeOfEverything(MovementContext context) {
DeployerFakePlayer player = getPlayer(context);
if (player == null)
return;
ItemStack held = player.getHeldItemMainhand();
if (!held.isEmpty()) {
dropItem(context, held);
player.setHeldItem(Hand.MAIN_HAND, ItemStack.EMPTY);
}
tryDisposeOfExcess(context);
}
private void tryDisposeOfExcess(MovementContext context) { private void tryDisposeOfExcess(MovementContext context) {
DeployerFakePlayer player = getPlayer(context); DeployerFakePlayer player = getPlayer(context);
if (player == null) if (player == null)

View file

@ -327,6 +327,8 @@ public class DeployerTileEntity extends KineticTileEntity {
timer = compound.getInt("Timer"); timer = compound.getInt("Timer");
deferredInventoryList = compound.getList("Inventory", NBT.TAG_COMPOUND); deferredInventoryList = compound.getList("Inventory", NBT.TAG_COMPOUND);
overflowItems = NBTHelper.readItemList(compound.getList("Overflow", NBT.TAG_COMPOUND)); overflowItems = NBTHelper.readItemList(compound.getList("Overflow", NBT.TAG_COMPOUND));
if (compound.contains("HeldItem"))
heldItem = ItemStack.read(compound.getCompound("HeldItem"));
super.read(compound); super.read(compound);
} }
@ -336,6 +338,7 @@ public class DeployerTileEntity extends KineticTileEntity {
compound.putString("State", NBTHelper.writeEnum(state)); compound.putString("State", NBTHelper.writeEnum(state));
compound.putInt("Timer", timer); compound.putInt("Timer", timer);
if (player != null) { if (player != null) {
compound.put("HeldItem", player.getHeldItemMainhand().serializeNBT());
ListNBT invNBT = new ListNBT(); ListNBT invNBT = new ListNBT();
player.inventory.write(invNBT); player.inventory.write(invNBT);
compound.put("Inventory", invNBT); compound.put("Inventory", invNBT);
@ -360,8 +363,6 @@ public class DeployerTileEntity extends KineticTileEntity {
@Override @Override
public void readClientUpdate(CompoundNBT tag) { public void readClientUpdate(CompoundNBT tag) {
reach = tag.getFloat("Reach"); reach = tag.getFloat("Reach");
if (tag.contains("HeldItem"))
heldItem = ItemStack.read(tag.getCompound("HeldItem"));
if (tag.contains("Particle")) { if (tag.contains("Particle")) {
ItemStack particleStack = ItemStack.read(tag.getCompound("Particle")); ItemStack particleStack = ItemStack.read(tag.getCompound("Particle"));
SandPaperItem.spawnParticles(VecHelper.getCenterOf(pos).add(getMovementVector().scale(2f)), particleStack, SandPaperItem.spawnParticles(VecHelper.getCenterOf(pos).add(getMovementVector().scale(2f)), particleStack,

View file

@ -77,8 +77,8 @@ public class DeployerTileEntityRenderer extends SafeTileEntityRenderer<DeployerT
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer(); ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
TransformType transform = TransformType.NONE; TransformType transform = TransformType.NONE;
boolean isBlockItem = (te.heldItem.getItem() instanceof BlockItem) boolean isBlockItem =
&& itemRenderer.getModelWithOverrides(te.heldItem).isGui3d(); (te.heldItem.getItem() instanceof BlockItem) && itemRenderer.getModelWithOverrides(te.heldItem).isGui3d();
if (displayMode) { if (displayMode) {
float scale = isBlockItem ? 1.25f : 1; float scale = isBlockItem ? 1.25f : 1;
@ -168,17 +168,17 @@ public class DeployerTileEntityRenderer extends SafeTileEntityRenderer<DeployerT
SuperByteBuffer hand = renderAndTransform(world, handPose, blockState, pos, false); SuperByteBuffer hand = renderAndTransform(world, handPose, blockState, pos, false);
double factor; double factor;
if (context.contraption.stalled || context.position == null) { if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) {
factor = MathHelper.sin(AnimationTickHolder.getRenderTick() * .5f) * .25f + .25f; factor = MathHelper.sin(AnimationTickHolder.getRenderTick() * .5f) * .25f + .25f;
} else { } else {
Vec3d center = VecHelper.getCenterOf(new BlockPos(context.position)); Vec3d center = VecHelper.getCenterOf(new BlockPos(context.position));
double distance = context.position.distanceTo(center); double distance = context.position.distanceTo(center);
double nextDistance = context.position.add(context.motion).distanceTo(center); double nextDistance = context.position.add(context.motion).distanceTo(center);
factor = .5f - MathHelper.lerp(Minecraft.getInstance().getRenderPartialTicks(), distance, nextDistance); factor = .5f - MathHelper.clamp(
MathHelper.lerp(Minecraft.getInstance().getRenderPartialTicks(), distance, nextDistance), 0, 1);
} }
Vec3d offset = new Vec3d(blockState.get(FACING).getDirectionVec()) Vec3d offset = new Vec3d(blockState.get(FACING).getDirectionVec()).scale(factor);
.scale(factor);
pole.translate(offset.x, offset.y, offset.z); pole.translate(offset.x, offset.y, offset.z);
hand.translate(offset.x, offset.y, offset.z); hand.translate(offset.x, offset.y, offset.z);

View file

@ -53,7 +53,7 @@ public class ToolEvents {
if (!tool.modifiesDrops()) if (!tool.modifiesDrops())
return; return;
BlockState state = event.getState(); BlockState state = event.getState();
if (!tool.canHarvestBlock(held, state)) if (!tool.canHarvestBlock(held, state) && !state.getMaterial().isToolNotRequired())
return; return;
IWorld world = event.getWorld(); IWorld world = event.getWorld();

View file

@ -80,7 +80,7 @@ public abstract class BeltAttachableLogisticalBlock extends AttachedLogisticalBl
if (filtering != null && (!filtering.test(stack) || stack.getCount() < filtering.getAmount())) if (filtering != null && (!filtering.test(stack) || stack.getCount() < filtering.getAmount()))
return false; return false;
if (!extracting.getShouldExtract().get()) if (!extracting.getShouldExtract().get())
return !filtering.anyAmount(); return true;
return !extracting.extractFromInventory(); return !extracting.extractFromInventory();
} }

View file

@ -101,8 +101,10 @@ public class ExtractorTileEntity extends SmartTileEntity {
protected boolean canExtract() { protected boolean canExtract() {
if (AllBlocks.BELT.typeOf(world.getBlockState(pos.down()))) { if (AllBlocks.BELT.typeOf(world.getBlockState(pos.down()))) {
TileEntity te = world.getTileEntity(pos.down()); TileEntity te = world.getTileEntity(pos.down());
if (te != null && te instanceof BeltTileEntity) { if (te instanceof BeltTileEntity) {
BeltTileEntity belt = (BeltTileEntity) te; BeltTileEntity belt = (BeltTileEntity) te;
if (belt.getSpeed() == 0)
return false;
BeltTileEntity controller = belt.getControllerTE(); BeltTileEntity controller = belt.getControllerTE();
if (controller != null) { if (controller != null) {
if (!controller.getInventory().canInsertFrom(belt.index, Direction.UP)) if (!controller.getInventory().canInsertFrom(belt.index, Direction.UP))

View file

@ -2,15 +2,19 @@ package com.simibubi.create.modules.logistics.block.transposer;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.IWrenchable;
import com.simibubi.create.modules.logistics.block.belts.BeltAttachableLogisticalBlock; import com.simibubi.create.modules.logistics.block.belts.BeltAttachableLogisticalBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemUseContext;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
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.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
@ -19,7 +23,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class TransposerBlock extends BeltAttachableLogisticalBlock { public class TransposerBlock extends BeltAttachableLogisticalBlock implements IWrenchable {
public static BooleanProperty POWERED = BlockStateProperties.POWERED; public static BooleanProperty POWERED = BlockStateProperties.POWERED;
@ -62,6 +66,30 @@ public class TransposerBlock extends BeltAttachableLogisticalBlock {
return AllBlocks.TRANSPOSER.getDefault(); return AllBlocks.TRANSPOSER.getDefault();
} }
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
World world = context.getWorld();
if (world.isRemote)
return ActionResultType.SUCCESS;
Direction blockFacing = getBlockFacing(state);
BlockState newState = state;
if (blockFacing.getAxis().isHorizontal())
newState = state.with(HORIZONTAL_FACING, blockFacing.getOpposite());
else
newState = state.cycle(UPWARD);
BlockPos pos = context.getPos();
world.setBlockState(pos, newState);
TileEntity te = world.getTileEntity(pos);
if (te instanceof TransposerTileEntity) {
TransposerTileEntity transposer = (TransposerTileEntity) te;
CompoundNBT compound = new CompoundNBT();
transposer.write(compound);
world.removeTileEntity(pos);
world.setTileEntity(pos, TileEntity.create(compound));
}
return ActionResultType.SUCCESS;
}
@Override @Override
public BlockState getStateForPlacement(BlockItemUseContext context) { public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState stateForPlacement = super.getStateForPlacement(context); BlockState stateForPlacement = super.getStateForPlacement(context);
@ -93,8 +121,7 @@ public class TransposerBlock extends BeltAttachableLogisticalBlock {
@Override @Override
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
Direction back = getBlockFacing(state).getOpposite(); return true;
return super.isValidPosition(state, worldIn, pos) || canAttachToSide(worldIn, pos, back);
} }
protected boolean reactsToRedstone() { protected boolean reactsToRedstone() {

View file

@ -1042,6 +1042,8 @@
"block.create.extractor.tooltip.summary": "_Takes_ _Items_ from an attached _Inventory_ and drops them onto the ground. Will not drop Items unless the space is clear. Can be assigned an item-stack as a _filter_.", "block.create.extractor.tooltip.summary": "_Takes_ _Items_ from an attached _Inventory_ and drops them onto the ground. Will not drop Items unless the space is clear. Can be assigned an item-stack as a _filter_.",
"block.create.extractor.tooltip.condition1": "When Powered by Redstone", "block.create.extractor.tooltip.condition1": "When Powered by Redstone",
"block.create.extractor.tooltip.behaviour1": "_Pauses_ the Extractor.", "block.create.extractor.tooltip.behaviour1": "_Pauses_ the Extractor.",
"block.create.extractor.tooltip.condition2": "Active Belt pulling",
"block.create.extractor.tooltip.behaviour2": "Extractors can pull items _from_ _belts_ reinforced with _brass_ _casing_. When the extractor is blocked, the _belt_ _will_ _stall_.",
"block.create.extractor.tooltip.control1": "R-Click on Filter Space", "block.create.extractor.tooltip.control1": "R-Click on Filter Space",
"block.create.extractor.tooltip.action1": "Assigns currently _held_ _stack_ as the _Filter_. The Extractor will pull the item _type_ and _count_ of the filter stack exclusively.", "block.create.extractor.tooltip.action1": "Assigns currently _held_ _stack_ as the _Filter_. The Extractor will pull the item _type_ and _count_ of the filter stack exclusively.",
@ -1049,6 +1051,8 @@
"block.create.transposer.tooltip.summary": "_Takes_ _items_ from an attached _Inventory_ and immediately puts them into the target _Inventory_. Can be assigned an item-stack as a _filter_.", "block.create.transposer.tooltip.summary": "_Takes_ _items_ from an attached _Inventory_ and immediately puts them into the target _Inventory_. Can be assigned an item-stack as a _filter_.",
"block.create.transposer.tooltip.condition1": "When Powered by Redstone", "block.create.transposer.tooltip.condition1": "When Powered by Redstone",
"block.create.transposer.tooltip.behaviour1": "_Pauses_ the Transposer.", "block.create.transposer.tooltip.behaviour1": "_Pauses_ the Transposer.",
"block.create.transposer.tooltip.condition2": "Active Belt pulling",
"block.create.transposer.tooltip.behaviour2": "Transposers can pull items _from_ _belts_ reinforced with _brass_ _casing_. When the transposer is backed up, the _belt_ _will_ _stall_.",
"block.create.transposer.tooltip.control1": "R-Click on Filter Space", "block.create.transposer.tooltip.control1": "R-Click on Filter Space",
"block.create.transposer.tooltip.action1": "Assigns currently _held_ _stack_ as the _Filter_. The Transposer will pull the item _type_ and _count_ of the filter stack exclusively.", "block.create.transposer.tooltip.action1": "Assigns currently _held_ _stack_ as the _Filter_. The Transposer will pull the item _type_ and _count_ of the filter stack exclusively.",
@ -1079,6 +1083,8 @@
"block.create.belt_funnel.tooltip": "FUNNEL", "block.create.belt_funnel.tooltip": "FUNNEL",
"block.create.belt_funnel.tooltip.summary": "_Collects_ _incoming_ _items_ and inserts them into the attached _Inventory_ if possible. Can collect items in the _world_ and items on a _belt_.", "block.create.belt_funnel.tooltip.summary": "_Collects_ _incoming_ _items_ and inserts them into the attached _Inventory_ if possible. Can collect items in the _world_ and items on a _belt_.",
"block.create.belt_funnel.tooltip.condition1": "Passive Belt pulling",
"block.create.belt_funnel.tooltip.behaviour1": "Funnels can pull items _from_ _belts_ when placed above them, either sideways or at the end. When a side-ways funnel is backed up, items on the _belt_ _will_ _not_ _stall_.",
"block.create.belt_tunnel.tooltip": "BELT TUNNEL", "block.create.belt_tunnel.tooltip": "BELT TUNNEL",
"block.create.belt_tunnel.tooltip.summary": "An aesthetic option for running your _Mechanical_ _Belts_ through walls. Belts have to be reinforced with _Brass_ _Casing_. Tunnels can _synchronize_ with _their_ _neighbours_, only letting items pass if all tunnels in the group have one waiting. [Ctrl]", "block.create.belt_tunnel.tooltip.summary": "An aesthetic option for running your _Mechanical_ _Belts_ through walls. Belts have to be reinforced with _Brass_ _Casing_. Tunnels can _synchronize_ with _their_ _neighbours_, only letting items pass if all tunnels in the group have one waiting. [Ctrl]",

View file

@ -0,0 +1,26 @@
{
"type": "crafting_shaped",
"pattern": [
" M ",
"SES",
" D "
],
"key": {
"M": {
"item": "minecraft:milk_bucket"
},
"S": {
"item": "minecraft:sugar"
},
"E": {
"item": "minecraft:egg"
},
"D": {
"item": "create:dough"
}
},
"result": {
"item": "minecraft:cake",
"count": 1
}
}