Flimsy Collision

- Fixed server crash on startup
- Fixed crash when entities get killed by anything other than players
- Pulleys no longer force push blocks below them
- Drill and Saw now applies damage to entities while moved in a contraption
- Made tooltip formatting a tad more lenient
- Added contraption collision to Pistons and Pulleys - applied by stationary blocks, other contraptions and entities. (needs polish)
This commit is contained in:
simibubi 2020-03-13 00:51:25 +01:00
parent 2c21902f1f
commit 6031d9fce1
22 changed files with 497 additions and 382 deletions

View file

@ -1,9 +1,12 @@
package com.simibubi.create.foundation.block;
import net.minecraft.client.renderer.color.IBlockColor;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public interface IHaveColorHandler {
@OnlyIn(Dist.CLIENT)
public IBlockColor getColorHandler();
}

View file

@ -53,9 +53,8 @@ public class TooltipHelper {
for (int i = 0; i < words.length; i++) {
String word = words[i];
if (word.matches("_.+_")) {
word = highlightColor + word.substring(1, word.length() - 1) + defaultColor;
}
if (word.matches("_.+_.?"))
word = highlightColor + word.replaceAll("\\_", "") + defaultColor;
boolean lastWord = i == words.length - 1;

View file

@ -5,8 +5,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.entity.Entity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
@ -28,17 +31,28 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
if (world.isRemote)
return;
if (stateVisited.getCollisionShape(world, pos).isEmpty())
if (stateVisited.getCollisionShape(world, pos).isEmpty()) {
DamageSource damageSource = getDamageSource();
if (damageSource == null)
return;
if (stateVisited.getBlockHardness(world, pos) == -1)
for (Entity entity : world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(pos))) {
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(stateVisited))
}
if (!canBreak(world, pos, stateVisited))
return;
context.data.put("BreakingPos", NBTUtil.writeBlockPos(pos));
context.stall = true;
}
protected DamageSource getDamageSource() {
return null;
}
@Override
public void stopMoving(MovementContext context) {
CompoundNBT data = context.data;
@ -84,7 +98,7 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
BlockState stateToBreak = world.getBlockState(breakingPos);
float blockHardness = stateToBreak.getBlockHardness(world, breakingPos);
if (!BlockBreakingKineticTileEntity.isBreakable(stateToBreak, blockHardness) || !canBreak(stateToBreak)) {
if (!canBreak(world, breakingPos, stateToBreak)) {
if (destroyProgress != 0) {
destroyProgress = 0;
data.remove("Progress");
@ -117,12 +131,12 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
data.putInt("Progress", destroyProgress);
}
protected boolean canBreak(BlockState state) {
return true;
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
float blockHardness = state.getBlockHardness(world, breakingPos);
return BlockBreakingKineticTileEntity.isBreakable(state, blockHardness);
}
protected void onBlockBroken(MovementContext context, BlockPos pos) {
}
}

View file

@ -4,6 +4,7 @@ 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.util.DamageSource;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@ -27,4 +28,9 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
return DrillTileEntityRenderer.renderInContraption(context);
}
@Override
protected DamageSource getDamageSource() {
return DrillBlock.damageSourceDrill;
}
}

View file

@ -11,6 +11,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
@ -29,8 +30,8 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
}
@Override
protected boolean canBreak(BlockState state) {
return super.canBreak(state) && state.isIn(BlockTags.LOGS);
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
return super.canBreak(world, breakingPos, state) && state.isIn(BlockTags.LOGS);
}
@Override
@ -57,4 +58,9 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
entity.setMotion(context.relativeMotion.scale(distance / 20f));
world.addEntity(entity);
}
@Override
protected DamageSource getDamageSource() {
return SawBlock.damageSourceSaw;
}
}

View file

@ -192,7 +192,10 @@ public abstract class Contraption {
return false;
ChassisTileEntity chassis = (ChassisTileEntity) te;
chassis.addAttachedChasses(frontier, visited);
for (BlockPos blockPos : chassis.getIncludedBlockPositions(movementDirection, false))
List<BlockPos> includedBlockPositions = chassis.getIncludedBlockPositions(movementDirection, false);
if (includedBlockPositions == null)
return false;
for (BlockPos blockPos : includedBlockPositions)
if (!visited.contains(blockPos))
frontier.add(blockPos);
return true;
@ -407,6 +410,8 @@ public abstract class Contraption {
if (AllBlocks.SAW.typeOf(state))
state = state.with(SawBlock.RUNNING, false);
if (world.getBlockState(targetPos).getBlockHardness(world, targetPos) == -1)
continue;
world.destroyBlock(targetPos, world.getBlockState(targetPos).getCollisionShape(world, targetPos).isEmpty());
world.setBlockState(targetPos, state, 3 | BlockFlags.IS_MOVING);
TileEntity tileEntity = world.getTileEntity(targetPos);

View file

@ -0,0 +1,251 @@
package com.simibubi.create.modules.contraptions.components.contraptions;
import java.util.HashMap;
import java.util.Map;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.components.actors.BlockBreakingMovementBehaviour;
import net.minecraft.block.BlockState;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.ReuseableStream;
import net.minecraft.util.math.AxisAlignedBB;
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.VoxelShape;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
public class ContraptionCollider {
static Map<Object, AxisAlignedBB> renderedBBs = new HashMap<>();
public static void collideEntities(ContraptionEntity contraptionEntity) {
if (Contraption.isFrozen())
return;
if (!contraptionEntity.collisionEnabled())
return;
World world = contraptionEntity.getEntityWorld();
Vec3d contraptionMotion = contraptionEntity.getMotion();
Contraption contraption = contraptionEntity.getContraption();
AxisAlignedBB bounds = contraptionEntity.getBoundingBox();
Vec3d contraptionPosition = contraptionEntity.getPositionVec();
if (contraption == null)
return;
if (bounds == null)
return;
for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, bounds.grow(1),
e -> e.getPushReaction() == PushReaction.NORMAL)) {
ReuseableStream<VoxelShape> potentialHits =
getPotentiallyCollidedShapes(world, contraption, contraptionPosition, entity);
if (potentialHits.createStream().count() == 0)
continue;
Vec3d positionOffset = contraptionPosition.scale(-1);
AxisAlignedBB entityBB = entity.getBoundingBox().offset(positionOffset).grow(1.0E-7D);
Vec3d entityMotion = entity.getMotion();
Vec3d relativeMotion = entityMotion.subtract(contraptionMotion);
Vec3d allowedMovement = Entity.getAllowedMovement(relativeMotion, entityBB, world,
ISelectionContext.forEntity(entity), potentialHits);
potentialHits.createStream()
.forEach(voxelShape -> pushEntityOutOfShape(entity, voxelShape, positionOffset));
if (allowedMovement.equals(relativeMotion))
continue;
if (allowedMovement.y != relativeMotion.y) {
entity.fall(entity.fallDistance, 1);
entity.fallDistance = 0;
entity.onGround = true;
}
if (entity instanceof PlayerEntity && !world.isRemote)
return;
entity.setMotion(allowedMovement.add(contraptionMotion));
entity.velocityChanged = true;
}
}
public static void pushEntityOutOfShape(Entity entity, VoxelShape voxelShape, Vec3d positionOffset) {
AxisAlignedBB entityBB = entity.getBoundingBox().offset(positionOffset);
Vec3d entityMotion = entity.getMotion();
if (!voxelShape.toBoundingBoxList().stream().anyMatch(entityBB::intersects))
return;
AxisAlignedBB shapeBB = voxelShape.getBoundingBox();
Direction bestSide = Direction.DOWN;
double bestOffset = 100;
double finalOffset = 0;
for (Direction face : Direction.values()) {
Axis axis = face.getAxis();
double d = axis == Axis.X ? entityBB.getXSize() + shapeBB.getXSize()
: axis == Axis.Y ? entityBB.getYSize() + shapeBB.getYSize()
: entityBB.getZSize() + shapeBB.getZSize();
d = d + .5f;
Vec3d nudge = new Vec3d(face.getDirectionVec()).scale(d);
AxisAlignedBB nudgedBB = entityBB.offset(nudge.getX(), nudge.getY(), nudge.getZ());
double nudgeDistance = face.getAxisDirection() == AxisDirection.POSITIVE ? -d : d;
double offset = voxelShape.getAllowedOffset(face.getAxis(), nudgedBB, nudgeDistance);
double abs = Math.abs(nudgeDistance - offset);
if (abs < Math.abs(bestOffset) && abs != 0) {
bestOffset = abs;
finalOffset = abs;
bestSide = face;
}
}
if (bestOffset != 0) {
entity.move(MoverType.SELF, new Vec3d(bestSide.getDirectionVec()).scale(finalOffset));
boolean positive = bestSide.getAxisDirection() == AxisDirection.POSITIVE;
double clamped;
switch (bestSide.getAxis()) {
case X:
clamped = positive ? Math.max(0, entityMotion.x) : Math.min(0, entityMotion.x);
entity.setMotion(clamped, entityMotion.y, entityMotion.z);
break;
case Y:
clamped = positive ? Math.max(0, entityMotion.y) : Math.min(0, entityMotion.y);
entity.setMotion(entityMotion.x, clamped, entityMotion.z);
entity.fall(entity.fallDistance, 1);
entity.fallDistance = 0;
entity.onGround = true;
break;
case Z:
clamped = positive ? Math.max(0, entityMotion.z) : Math.min(0, entityMotion.z);
entity.setMotion(entityMotion.x, entityMotion.y, clamped);
break;
}
}
}
public static ReuseableStream<VoxelShape> getPotentiallyCollidedShapes(World world, Contraption contraption,
Vec3d contraptionPosition, Entity entity) {
AxisAlignedBB blockScanBB = entity.getBoundingBox().offset(contraptionPosition.scale(-1)).grow(.5f);
BlockPos min = new BlockPos(blockScanBB.minX, blockScanBB.minY, blockScanBB.minZ);
BlockPos max = new BlockPos(blockScanBB.maxX, blockScanBB.maxY, blockScanBB.maxZ);
ReuseableStream<VoxelShape> potentialHits =
new ReuseableStream<>(BlockPos.getAllInBox(min, max).filter(contraption.blocks::containsKey).map(p -> {
BlockState blockState = contraption.blocks.get(p).state;
BlockPos pos = contraption.blocks.get(p).pos;
VoxelShape collisionShape = blockState.getCollisionShape(world, p);
return collisionShape.withOffset(pos.getX(), pos.getY(), pos.getZ());
}));
return potentialHits;
}
public static boolean collideBlocks(ContraptionEntity contraptionEntity) {
if (Contraption.isFrozen())
return true;
if (!contraptionEntity.collisionEnabled())
return false;
World world = contraptionEntity.getEntityWorld();
Vec3d motion = contraptionEntity.getMotion();
Contraption contraption = contraptionEntity.getContraption();
AxisAlignedBB bounds = contraptionEntity.getBoundingBox();
Vec3d position = contraptionEntity.getPositionVec();
BlockPos gridPos = new BlockPos(position);
if (contraption == null)
return false;
if (bounds == null)
return false;
if (motion.equals(Vec3d.ZERO))
return false;
Direction movementDirection = Direction.getFacingFromVector(motion.x, motion.y, motion.z);
// Blocks in the world
if (movementDirection.getAxisDirection() == AxisDirection.POSITIVE)
gridPos = gridPos.offset(movementDirection);
if (isCollidingWithWorld(world, contraption, gridPos, movementDirection))
return true;
// Other moving Contraptions
for (ContraptionEntity otherContraptionEntity : world.getEntitiesWithinAABB(ContraptionEntity.class,
bounds.grow(1), e -> !e.equals(contraptionEntity))) {
if (!otherContraptionEntity.collisionEnabled())
continue;
Vec3d otherMotion = otherContraptionEntity.getMotion();
Contraption otherContraption = otherContraptionEntity.getContraption();
AxisAlignedBB otherBounds = otherContraptionEntity.getBoundingBox();
Vec3d otherPosition = otherContraptionEntity.getPositionVec();
if (otherContraption == null)
return false;
if (otherBounds == null)
return false;
if (!bounds.offset(motion).intersects(otherBounds.offset(otherMotion)))
continue;
for (BlockPos colliderPos : contraption.getColliders(world, movementDirection)) {
colliderPos = colliderPos.add(gridPos).subtract(new BlockPos(otherPosition));
if (!otherContraption.blocks.containsKey(colliderPos))
continue;
return true;
}
}
return false;
}
public static boolean isCollidingWithWorld(World world, Contraption contraption, BlockPos anchor,
Direction movementDirection) {
for (BlockPos pos : contraption.getColliders(world, movementDirection)) {
BlockPos colliderPos = pos.add(anchor);
if (!world.isBlockPresent(colliderPos))
return true;
BlockState collidedState = world.getBlockState(colliderPos);
BlockInfo blockInfo = contraption.blocks.get(pos);
if (blockInfo.state.getBlock() instanceof IPortableBlock) {
IPortableBlock block = (IPortableBlock) blockInfo.state.getBlock();
if (block.getMovementBehaviour() instanceof BlockBreakingMovementBehaviour) {
BlockBreakingMovementBehaviour behaviour =
(BlockBreakingMovementBehaviour) block.getMovementBehaviour();
if (!behaviour.canBreak(world, colliderPos, collidedState)
&& !collidedState.getCollisionShape(world, pos).isEmpty()) {
return true;
}
continue;
}
}
if (AllBlocks.PULLEY_MAGNET.typeOf(collidedState) && pos.equals(BlockPos.ZERO)
&& movementDirection == Direction.UP)
continue;
if (!collidedState.getMaterial().isReplaceable()
&& !collidedState.getCollisionShape(world, colliderPos).isEmpty()) {
return true;
}
}
return false;
}
}

View file

@ -9,7 +9,9 @@ import com.simibubi.create.AllEntities;
import com.simibubi.create.AllPackets;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.BearingContraption;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.LinearActuatorTileEntity;
import net.minecraft.block.material.PushReaction;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
@ -93,6 +95,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
return this;
}
public boolean collisionEnabled() {
return stationary && controllerTE instanceof LinearActuatorTileEntity;
}
@Override
public void tick() {
if (contraption == null) {
@ -102,8 +108,33 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
attachToController();
Entity e = getRidingEntity();
if (e != null) {
Entity mountedEntity = getRidingEntity();
if (mountedEntity != null) {
tickAsPassenger(mountedEntity);
return;
}
if (getMotion().length() < 1 / 4098f)
setMotion(Vec3d.ZERO);
move(getMotion().x, getMotion().y, getMotion().z);
if (ContraptionCollider.collideBlocks(this))
controllerTE.collided();
tickActors(new Vec3d(posX - prevPosX, posY - prevPosY, posZ - prevPosZ));
prevYaw = yaw;
prevPitch = pitch;
prevRoll = roll;
super.tick();
}
public void collisionTick() {
ContraptionCollider.collideEntities(this);
}
public void tickAsPassenger(Entity e) {
Entity riding = e;
while (riding.getRidingEntity() != null)
riding = riding.getRidingEntity();
@ -111,6 +142,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (riding instanceof BoatEntity)
movementVector = new Vec3d(posX - prevPosX, posY - prevPosY, posZ - prevPosZ);
Vec3d motion = movementVector.normalize();
if (motion.length() > 0) {
targetYaw = yawFromVector(motion);
if (targetYaw < 0)
@ -119,15 +151,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
yaw += 360;
}
// if (Math.abs(getShortestAngleDiff(yaw, targetYaw)) >= 175) {
// initialAngle += 180;
// yaw += 180;
// prevYaw = yaw;
// } else {
float speed = 0.2f;
prevYaw = yaw;
yaw = angleLerp(speed, yaw, targetYaw);
// }
yaw = angleLerp(0.2f, yaw, targetYaw);
boolean wasStalled = isStalled();
tickActors(movementVector);
@ -142,18 +167,6 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
motionBeforeStall = Vec3d.ZERO;
}
super.tick();
return;
}
if (getMotion().length() > 1 / 4098f)
move(getMotion().x, getMotion().y, getMotion().z);
tickActors(new Vec3d(posX - prevPosX, posY - prevPosY, posZ - prevPosZ));
prevYaw = yaw;
prevPitch = pitch;
prevRoll = roll;
super.tick();
}
@ -237,14 +250,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
}
}
public void moveTo(double x, double y, double z) {
move(x - posX, y - posY, z - posZ);
}
public void move(double x, double y, double z) {
// Collision and stuff
setPosition(posX + x, posY + y, posZ + z);
}
@ -259,9 +265,6 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
}
public void rotate(double roll, double yaw, double pitch) {
// Collision and stuff
this.yaw += yaw;
this.pitch += pitch;
this.roll += roll;
@ -397,9 +400,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
public void disassemble() {
if (getContraption() != null) {
float yaw = getYaw(1);
getContraption().disassemble(world, new BlockPos(getPositionVec().add(.5, .5, .5)),
new Vec3d(getRoll(1), yaw, getPitch(1)));
new Vec3d(getRoll(1), getYaw(1), getPitch(1)));
}
remove();
}
@ -440,8 +442,13 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
}
@Override
public void setMotion(Vec3d motionIn) {
// Make sure nothing can move contraptions out of the way
public void setMotion(Vec3d motionIn) {
}
@Override
public PushReaction getPushReaction() {
return PushReaction.IGNORE;
}
public void setContraptionMotion(Vec3d vec) {

View file

@ -68,4 +68,6 @@ public interface IControlContraption {
}
public void collided();
}

View file

@ -29,7 +29,7 @@ public class ClockworkBearingBlock extends BearingBlock implements IWithTileEnti
if (!worldIn.isRemote) {
withTileEntityDo(worldIn, pos, te -> {
if (te.running) {
te.disassembleConstruct();
te.disassemble();
return;
}
te.assembleNextTick = true;

View file

@ -46,7 +46,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
}
if (running && Contraption.isFrozen())
disassembleConstruct();
disassemble();
if (!world.isRemote && assembleNextTick) {
assembleNextTick = false;
@ -57,12 +57,11 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
hourHand.getContraption().stop(world);
if (minuteHand != null)
minuteHand.getContraption().stop(world);
disassembleConstruct();
disassemble();
}
return;
} else {
assembleConstruct();
}
} else
assemble();
return;
}
@ -148,7 +147,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
return speed;
}
public void assembleConstruct() {
public void assemble() {
Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct
@ -182,7 +181,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
sendData();
}
public void disassembleConstruct() {
public void disassemble() {
if (!running)
return;
@ -280,8 +279,12 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
@Override
public void remove() {
if (!world.isRemote)
disassembleConstruct();
disassemble();
super.remove();
}
@Override
public void collided() {
}
}

View file

@ -30,7 +30,7 @@ public class MechanicalBearingBlock extends BearingBlock implements IWithTileEnt
if (!worldIn.isRemote) {
withTileEntityDo(worldIn, pos, te -> {
if (te.running) {
te.disassembleConstruct();
te.disassemble();
return;
}
te.assembleNextTick = true;

View file

@ -81,7 +81,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
@Override
public void remove() {
if (!world.isRemote)
disassembleConstruct();
disassemble();
super.remove();
}
@ -144,7 +144,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
return speed;
}
public void assembleConstruct() {
public void assemble() {
Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct
@ -168,7 +168,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
updateGeneratedRotation();
}
public void disassembleConstruct() {
public void disassemble() {
if (!running)
return;
if (movedContraption != null)
@ -190,7 +190,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
clientAngleDiff /= 2;
if (running && Contraption.isFrozen())
disassembleConstruct();
disassemble();
if (!world.isRemote && assembleNextTick) {
assembleNextTick = false;
@ -201,13 +201,13 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|| movedContraption.getContraption().blocks.isEmpty())) {
if (movedContraption != null)
movedContraption.getContraption().stop(world);
disassembleConstruct();
disassemble();
}
return;
} else {
if (speed == 0 && !isWindmill)
return;
assembleConstruct();
assemble();
}
return;
}
@ -275,4 +275,8 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
});
}
@Override
public void collided() {
}
}

View file

@ -50,16 +50,23 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
super.tick();
boolean contraptionPresent = movedContraption != null;
if (contraptionPresent)
if (contraptionPresent) {
movedContraption.collisionTick();
if (!movedContraption.isAlive())
movedContraption = null;
}
if (world.isRemote)
clientOffsetDiff *= .75f;
if (waitingForSpeedChange) {
if (waitingForSpeedChange && contraptionPresent) {
if (world.isRemote) {
float syncSpeed = clientOffsetDiff / 2f;
offset += syncSpeed;
movedContraption.setContraptionMotion(toMotionVector(syncSpeed));
return;
}
movedContraption.setContraptionMotion(Vec3d.ZERO);
// movedContraption.setMotion(Vec3d.ZERO);
return;
}
@ -72,7 +79,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
sendData();
return;
}
assembleConstruct();
assemble();
return;
}
@ -96,6 +103,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
offset = offset <= 0 ? 0 : extensionRange;
if (!world.isRemote) {
applyContraptionMotion();
applyContraptionPosition();
tryDisassemble();
if (waitingForSpeedChange) {
forceMove = true;
@ -134,7 +142,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
public void remove() {
this.removed = true;
if (!world.isRemote)
disassembleConstruct();
disassemble();
super.remove();
}
@ -185,9 +193,9 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
}
protected abstract void assembleConstruct();
public abstract void disassemble();
protected abstract void disassembleConstruct();
protected abstract void assemble();
protected abstract int getExtensionRange();
@ -203,7 +211,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
protected void tryDisassemble() {
if (removed) {
disassembleConstruct();
disassemble();
return;
}
if (movementMode.get() == MovementMode.MOVE_NEVER_PLACE) {
@ -215,7 +223,18 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
waitingForSpeedChange = true;
return;
}
disassembleConstruct();
disassemble();
}
@Override
public void collided() {
if (world.isRemote) {
waitingForSpeedChange = true;
return;
}
offset = getGridOffset(offset - getMovementSpeed());
applyContraptionPosition();
tryDisassemble();
}
protected void applyContraptionMotion() {
@ -229,6 +248,8 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
}
protected void applyContraptionPosition() {
if (movedContraption == null)
return;
Vec3d vec = toPosition(offset);
movedContraption.setPosition(vec.x, vec.y, vec.z);
if (getSpeed() == 0 || waitingForSpeedChange)

View file

@ -5,6 +5,7 @@ import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionCollider;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.DirectionalExtenderScrollOptionSlot;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
@ -39,11 +40,20 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
}
@Override
public void assembleConstruct() {
public void assemble() {
Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct
PistonContraption contraption = PistonContraption.movePistonAt(world, pos, direction, getMovementSpeed() < 0);
Direction movementDirection = getSpeed() > 0 ? direction : direction.getOpposite();
if (contraption != null) {
BlockPos anchor = contraption.getAnchor().offset(direction, contraption.initialExtensionProgress);
if (ContraptionCollider.isCollidingWithWorld(world, contraption, anchor.offset(movementDirection),
movementDirection))
contraption = null;
}
if (contraption == null)
return;
@ -69,7 +79,7 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
}
@Override
public void disassembleConstruct() {
public void disassemble() {
if (!running)
return;
if (!removed)
@ -86,6 +96,13 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
AllBlocks.MECHANICAL_PISTON.get().onBlockHarvested(world, pos, getBlockState(), null);
}
@Override
public void collided() {
super.collided();
if (!running && getSpeed() > 0)
assembleNextTick = true;
}
@Override
public float getMovementSpeed() {
float movementSpeed = getSpeed() / 512f;
@ -138,82 +155,4 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
: ((PistonContraption) movedContraption.getContraption()).initialExtensionProgress;
}
// private boolean hasBlockCollisions(float newOffset) {
// if (PistonContraption.isFrozen())
// return true;
//
// Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
// BlockPos relativePos = BlockPos.ZERO.offset(movementDirection, getModulatedOffset(newOffset));
//
// // Other moving Pistons
// int maxPossibleRange = parameters.maxPistonPoles.get() + parameters.maxChassisRange.get()
// + parameters.maxChassisForTranslation.get();
// Iterator<MechanicalPistonTileEntity> iterator = Create.constructHandler.getOtherMovingPistonsInWorld(this)
// .iterator();
// pistonLoop: while (iterator.hasNext()) {
// MechanicalPistonTileEntity otherPiston = iterator.next();
//
// if (otherPiston == this)
// continue;
// if (!otherPiston.running || otherPiston.movedContraption == null) {
// iterator.remove();
// continue;
// }
// if (otherPiston.pos.manhattanDistance(pos) > maxPossibleRange * 2)
// continue;
//
// Direction otherMovementDirection = otherPiston.getBlockState().get(BlockStateProperties.FACING);
// BlockPos otherRelativePos = BlockPos.ZERO.offset(otherMovementDirection,
// getModulatedOffset(otherPiston.offset));
//
// for (AxisAlignedBB tBB : Arrays.asList(movedContraption.constructCollisionBox,
// movedContraption.pistonCollisionBox)) {
// for (AxisAlignedBB oBB : Arrays.asList(otherPiston.movedContraption.constructCollisionBox,
// otherPiston.movedContraption.pistonCollisionBox)) {
// if (tBB == null || oBB == null)
// continue;
//
// boolean frontalCollision = otherMovementDirection == movementDirection.getOpposite();
// BlockPos thisColliderOffset = relativePos.offset(movementDirection,
// frontalCollision ? (getMovementSpeed() > 0 ? 1 : -1) : 0);
// AxisAlignedBB thisBB = tBB.offset(thisColliderOffset);
// AxisAlignedBB otherBB = oBB.offset(otherRelativePos);
//
// if (thisBB.intersects(otherBB)) {
// boolean actuallyColliding = false;
// for (BlockPos colliderPos : movedContraption.getColliders(world, movementDirection)) {
// colliderPos = colliderPos.add(thisColliderOffset).subtract(otherRelativePos);
// if (!otherPiston.movedContraption.blocks.containsKey(colliderPos))
// continue;
// actuallyColliding = true;
// }
// if (!actuallyColliding)
// continue pistonLoop;
// hadCollisionWithOtherPiston = true;
// return true;
// }
//
// }
// }
//
// }
//
// if (!running)
// return false;
//
// // Other Blocks in world
// for (BlockPos pos : movedContraption.getColliders(world,
// getMovementSpeed() > 0 ? movementDirection : movementDirection.getOpposite())) {
// BlockPos colliderPos = pos.add(relativePos);
//
// if (!world.isBlockPresent(colliderPos))
// return true;
// if (!world.getBlockState(colliderPos).getMaterial().isReplaceable()
// && !world.getBlockState(colliderPos).getCollisionShape(world, colliderPos).isEmpty())
// return true;
// }
//
// return false;
// }
}

View file

@ -1,167 +0,0 @@
/*package com.simibubi.create.modules.contraptions.receivers.constructs.piston;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.simibubi.create.Create;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.world.IWorld;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class MovingConstructHandler {
static List<AxisAlignedBB> renderedBBs = new LinkedList<>();
static Map<IWorld, List<MechanicalPistonTileEntity>> movingPistons = new HashMap<>();
public void onLoadWorld(IWorld world) {
movingPistons.put(world, new ArrayList<>());
Create.logger.debug("Prepared Construct List for " + world.getDimension().getType().getRegistryName());
}
public void onUnloadWorld(IWorld world) {
movingPistons.remove(world);
Create.logger.debug("Removed Construct List for " + world.getDimension().getType().getRegistryName());
}
// public static void moveEntities(MechanicalPistonTileEntity te, float movementSpeed, Direction movementDirection,
// float newOffset) {
// if (PistonContraption.isFrozen())
// return;
//
// World world = te.getWorld();
// Vec3d movementVec = new Vec3d(te.getBlockState().get(BlockStateProperties.FACING).getDirectionVec());
// Contraption construct = te.movedContraption;
//
//// if (world.isRemote) {
//// renderedBBs.clear();
//// if (construct.pistonCollisionBox != null)
//// renderedBBs.add(construct.pistonCollisionBox.offset(te.getConstructOffset(0)));
//// if (construct.constructCollisionBox != null)
//// renderedBBs.add(construct.constructCollisionBox.offset(te.getConstructOffset(0)));
////
//// }
//
// if (construct.getCollisionBoxFront() != null) {
// AxisAlignedBB constructBB = construct.getCollisionBoxFront().offset(te.getConstructOffset(0)).grow(.5f);
//
// for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, constructBB,
// e -> e.getPushReaction() == PushReaction.NORMAL)) {
//
// AxisAlignedBB entityScanBB = entity.getBoundingBox().offset(movementVec.scale(-1 * newOffset))
// .grow(.5f);
// BlockPos min = new BlockPos(entityScanBB.minX, entityScanBB.minY, entityScanBB.minZ);
// BlockPos max = new BlockPos(entityScanBB.maxX, entityScanBB.maxY, entityScanBB.maxZ);
//
// Stream<VoxelShape> hits = BlockPos.getAllInBox(min, max).filter(construct.blocks::containsKey)
// .map(pos -> {
// Vec3d vec = new Vec3d(pos).add(te.getConstructOffset(te.getMovementSpeed() > 0 ? 1 : 0));
// return construct.blocks.get(pos).state.getShape(world, new BlockPos(vec)).withOffset(vec.x,
// vec.y, vec.z);
// });
// ReuseableStream<VoxelShape> potentialHits = new ReuseableStream<>(hits);
//
// AxisAlignedBB entityBB = entity.getBoundingBox();
// Vec3d motion = entity.getMotion();
// Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(-movementSpeed).add(motion);
// Vec3d allowedMovement = Entity.getAllowedMovement(movement, entityBB, world,
// ISelectionContext.forEntity(entity), potentialHits);
//
// for (Object shape : potentialHits.createStream().toArray()) {
// VoxelShape voxelShape = (VoxelShape) shape;
// if (!entityBB.intersects(voxelShape.getBoundingBox()))
// continue;
//
// Direction bestSide = Direction.DOWN;
// double bestOffset = 100;
// double finalOffset = 0;
//
// for (Direction face : Direction.values()) {
// Axis axis = face.getAxis();
// double d = axis == Axis.X ? entityBB.getXSize()
// : axis == Axis.Y ? entityBB.getYSize() : entityBB.getZSize();
// d = d + 1.5f;
//
// Vec3d nudge = new Vec3d(face.getDirectionVec()).scale(d);
// AxisAlignedBB nudgedBB = entityBB.offset(nudge.getX(), nudge.getY(), nudge.getZ());
// double nudgeDistance = face.getAxisDirection() == AxisDirection.POSITIVE ? -d : d;
// double offset = voxelShape.getAllowedOffset(face.getAxis(), nudgedBB, nudgeDistance);
// double abs = Math.abs(nudgeDistance - offset);
// if (abs < Math.abs(bestOffset) && abs != 0) {
// bestOffset = abs;
// finalOffset = abs;
// bestSide = face;
// }
// }
//
// if (bestOffset != 0) {
// entity.move(MoverType.SELF, new Vec3d(bestSide.getDirectionVec()).scale(finalOffset));
// switch (bestSide.getAxis()) {
// case X:
// entity.setMotion(0, motion.y, motion.z);
// break;
// case Y:
// entity.setMotion(motion.x, bestSide == Direction.UP ? movementSpeed + 1 / 8f : 0, motion.z);
// entity.fall(entity.fallDistance, 1);
// entity.fallDistance = 0;
// entity.onGround = true;
// break;
// case Z:
// entity.setMotion(motion.x, motion.y, 0);
// break;
// }
//
// break;
// }
// }
//
// if (!allowedMovement.equals(movement)) {
// if (allowedMovement.y != movement.y) {
// entity.fall(entity.fallDistance, 1);
// entity.fallDistance = 0;
// entity.onGround = true;
// }
// if (entity instanceof PlayerEntity && !world.isRemote)
// return;
// entity.setMotion(allowedMovement.subtract(movement.subtract(motion)));
// entity.velocityChanged = true;
// }
//
// }
// }
// }
public void add(MechanicalPistonTileEntity mechanicalPistonTileEntity) {
movingPistons.get(mechanicalPistonTileEntity.getWorld()).add(mechanicalPistonTileEntity);
}
public void remove(MechanicalPistonTileEntity mechanicalPistonTileEntity) {
movingPistons.get(mechanicalPistonTileEntity.getWorld()).remove(mechanicalPistonTileEntity);
}
public List<MechanicalPistonTileEntity> getOtherMovingPistonsInWorld(
MechanicalPistonTileEntity mechanicalPistonTileEntity) {
return movingPistons.get(mechanicalPistonTileEntity.getWorld());
}
// @SubscribeEvent
// @OnlyIn(value = Dist.CLIENT)
// public static void onRenderWorld(RenderWorldLastEvent event) {
// for (AxisAlignedBB bb : renderedBBs) {
// TessellatorHelper.prepareForDrawing();
// GlStateManager.disableTexture();
// GlStateManager.lineWidth(3);
// int color = ColorHelper.rainbowColor(renderedBBs.indexOf(bb) * 170);
// WorldRenderer.drawSelectionBoundingBox(bb.grow(1 / 256f), (color >> 16 & 0xFF) / 256f,
// (color >> 8 & 0xFF) / 256f, (color & 0xFF) / 256f, 1);
// GlStateManager.lineWidth(1);
// GlStateManager.enableTexture();
// TessellatorHelper.cleanUpAfterDrawing();
// }
// }
}*/

View file

@ -131,25 +131,25 @@ public class PistonContraption extends Contraption {
return true;
for (int offset = 0; offset <= AllConfigs.SERVER.kinetics.maxChassisRange.get(); offset++) {
if (offset == 1 && retracting)
break;
return true;
BlockPos currentPos = pos.offset(orientation, offset + initialExtensionProgress);
if (!world.isBlockPresent(currentPos))
return false;
BlockState state = world.getBlockState(currentPos);
if (state.getMaterial().isReplaceable())
break;
return true;
if (state.getCollisionShape(world, currentPos).isEmpty())
break;
return true;
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(state) && state.get(FACING) == direction.getOpposite())
break;
return true;
if (!BlockMovementTraits.movementAllowed(world, currentPos))
return retracting;
frontier.add(currentPos);
if (BlockMovementTraits.notSupportive(state, orientation))
break;
}
return true;
}
return false; // too many
}
@Override
public void add(BlockPos pos, Pair<BlockInfo, TileEntity> capture) {

View file

@ -4,7 +4,6 @@ import com.simibubi.create.modules.contraptions.components.contraptions.AllContr
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@ -22,7 +21,7 @@ public class PulleyContraption extends Contraption {
return null;
PulleyContraption construct = new PulleyContraption();
construct.initialOffset = initialOffset;
if (!construct.searchMovedStructure(world, pos, Direction.DOWN))
if (!construct.searchMovedStructure(world, pos, null))
return null;
construct.initActors(world);
return construct;

View file

@ -5,6 +5,7 @@ import com.simibubi.create.AllTileEntities;
import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionCollider;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.LinearActuatorTileEntity;
@ -30,7 +31,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
}
@Override
protected void assembleConstruct() {
protected void assemble() {
if (speed == 0)
return;
if (offset >= getExtensionRange() && getSpeed() > 0)
@ -43,6 +44,14 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
BlockPos anchor = pos.down((int) (offset + 1));
initialOffset = (int) (offset);
PulleyContraption contraption = PulleyContraption.assemblePulleyAt(world, anchor, (int) offset);
if (contraption != null) {
Direction movementDirection = getSpeed() > 0 ? Direction.DOWN : Direction.UP;
if (ContraptionCollider.isCollidingWithWorld(world, contraption, anchor.offset(movementDirection),
movementDirection))
contraption = null;
}
if (contraption == null && getSpeed() > 0)
return;
@ -66,7 +75,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
}
@Override
protected void disassembleConstruct() {
public void disassemble() {
if (!running)
return;
offset = getGridOffset(offset);
@ -124,7 +133,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
if (stateBelow.getMaterial().isReplaceable() || stateBelow.getShape(world, posBelow).isEmpty())
return;
disassembleConstruct();
disassemble();
assembleNextTick = true;
}

View file

@ -53,10 +53,11 @@ import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IEnviromentBlockReader;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraft.world.storage.loot.LootParameters;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.Tags;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
@ -317,6 +318,7 @@ public class BeltBlock extends HorizontalKineticBlock
}
@Override
@OnlyIn(Dist.CLIENT)
public boolean addDestroyEffects(BlockState state, World world, BlockPos pos, ParticleManager manager) {
// From Particle Manager, but reduced density for belts with lots of boxes
VoxelShape voxelshape = state.getShape(world, pos);
@ -603,25 +605,9 @@ public class BeltBlock extends HorizontalKineticBlock
}
@Override
@OnlyIn(Dist.CLIENT)
public IBlockColor getColorHandler() {
return color;
}
private static BeltColor color = new BeltColor();
private static class BeltColor implements IBlockColor {
@Override
public int getColor(BlockState state, IEnviromentBlockReader reader, BlockPos pos, int layer) {
TileEntity tileEntity = reader.getTileEntity(pos);
if (tileEntity instanceof BeltTileEntity) {
BeltTileEntity te = (BeltTileEntity) tileEntity;
if (te.color != -1)
return te.color;
}
return 0;
}
return new BeltColor();
}
}

View file

@ -0,0 +1,25 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.color.IBlockColor;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IEnviromentBlockReader;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
class BeltColor implements IBlockColor {
@Override
public int getColor(BlockState state, IEnviromentBlockReader reader, BlockPos pos, int layer) {
TileEntity tileEntity = reader.getTileEntity(pos);
if (tileEntity instanceof BeltTileEntity) {
BeltTileEntity te = (BeltTileEntity) tileEntity;
if (te.color != -1)
return te.color;
}
return 0;
}
}

View file

@ -152,7 +152,10 @@ public class ToolEvents {
@SubscribeEvent
public static void shadowSteelToolsDropMoreXPonKill(LivingExperienceDropEvent event) {
ItemStack heldItemMainhand = event.getAttackingPlayer().getHeldItemMainhand();
PlayerEntity attackingPlayer = event.getAttackingPlayer();
if (attackingPlayer == null)
return;
ItemStack heldItemMainhand = attackingPlayer.getHeldItemMainhand();
if (heldItemMainhand.getItem() instanceof ShadowSteelToolItem) {
int level = EnchantmentHelper.getEnchantmentLevel(Enchantments.LOOTING, heldItemMainhand);
float modifier = 1 + event.getEntity().world.getRandom().nextFloat() * level;