From 5db014c45b42004344bb29127d4bcc579a0c6682 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Mon, 9 Dec 2019 13:32:39 +0100 Subject: [PATCH] Better Acting - Contraption actors can now expose a few more properties and behaviours. - Contraption actors can save data within the context - Redstone Contacts now work when being rotated - Fixed harvester and drill offsets and their motion-aware animation - Fixed Mounted contraptions calculating their yaw inconsistently (again) --- .../create/foundation/utility/VecHelper.java | 15 +++- .../contraptions/receivers/DrillBlock.java | 24 ++--- .../receivers/DrillTileEntityRenderer.java | 5 +- .../receivers/HarvesterBlock.java | 27 +++--- .../HarvesterTileEntityRenderer.java | 11 +-- .../receivers/contraptions/Contraption.java | 8 +- .../contraptions/ContraptionEntity.java | 87 ++++++++++++------- .../ContraptionEntityRenderer.java | 18 ++-- .../contraptions/IHaveMovementBehavior.java | 70 +++++++++------ .../bearing/MechanicalBearingTileEntity.java | 2 +- .../contraptions/redstone/ContactBlock.java | 31 +++++-- 11 files changed, 188 insertions(+), 110 deletions(-) diff --git a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java index cc22db867..ff1fba149 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java @@ -4,6 +4,7 @@ import java.util.Random; import net.minecraft.nbt.DoubleNBT; import net.minecraft.nbt.ListNBT; +import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -11,9 +12,15 @@ import net.minecraft.util.math.Vec3i; public class VecHelper { - public static Vec3d rotate(Vec3d vec, float deg, Axis axis) { - float angle = (float) (deg / 180f * Math.PI); + public static Vec3d rotate(Vec3d vec, double xRot, double yRot, double zRot) { + return rotate(rotate(rotate(vec, xRot, Axis.X), yRot, Axis.Y), zRot, Axis.Z); + } + public static Vec3d rotate(Vec3d vec, double deg, Axis axis) { + if (deg == 0) + return vec; + + float angle = (float) (deg / 180f * Math.PI); double sin = MathHelper.sin(angle); double cos = MathHelper.cos(angle); double x = vec.x; @@ -29,6 +36,10 @@ public class VecHelper { return vec; } + public static boolean isVecPointingTowards(Vec3d vec, Direction direction) { + return new Vec3d(direction.getDirectionVec()).distanceTo(vec.normalize()) < .75; + } + public static Vec3d getCenterOf(Vec3i pos) { return new Vec3d(pos).add(.5f, .5f, .5f); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillBlock.java index 68df0d49c..35f6fe925 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillBlock.java @@ -5,6 +5,7 @@ import java.util.List; import com.simibubi.create.foundation.block.IRenderUtilityBlock; import com.simibubi.create.foundation.block.IWithTileEntity; import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VoxelShapers; import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock; import com.simibubi.create.modules.contraptions.receivers.contraptions.IHaveMovementBehavior; @@ -85,18 +86,22 @@ public class DrillBlock extends DirectionalKineticBlock } @Override - public void visitPosition(MovementContext context) { - Direction movement = context.getMovementDirection(); - -// BlockState block = context.state; -// if (movement == block.get(FACING).getOpposite()) -// return; + public boolean isActive(MovementContext context) { + return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.get(FACING).getOpposite()); + } + @Override + public Vec3d getActiveAreaOffset(MovementContext context) { + return new Vec3d(context.state.get(FACING).getDirectionVec()).scale(.65f); + } + + @Override + public void visitNewPosition(MovementContext context, BlockPos pos) { World world = context.world; - BlockPos pos = context.currentGridPos; -// pos = pos.offset(movement); BlockState stateVisited = world.getBlockState(pos); + if (world.isRemote) + return; if (stateVisited.getCollisionShape(world, pos).isEmpty()) return; if (stateVisited.getBlockHardness(world, pos) == -1) @@ -108,8 +113,7 @@ public class DrillBlock extends DirectionalKineticBlock for (ItemStack stack : drops) { ItemEntity itemEntity = new ItemEntity(world, pos.getX() + .5f, pos.getY() + .25f, pos.getZ() + .5f, stack); - itemEntity.setMotion( - new Vec3d(movement.getDirectionVec()).add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f)); + itemEntity.setMotion(context.motion.add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f)); world.addEntity(itemEntity); } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillTileEntityRenderer.java index e82bca1f7..07deafce9 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillTileEntityRenderer.java @@ -6,6 +6,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.modules.contraptions.base.IRotate; import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; @@ -29,7 +30,9 @@ public class DrillTileEntityRenderer extends KineticTileEntityRenderer { BlockState state = context.state; SuperByteBuffer buffer = CreateClient.bufferCache.renderBlockState(KINETIC_TILE, getRenderedBlockState(state)); - float speed = (float) (context.getMovementDirection() == state.get(FACING) ? context.getAnimationSpeed() : 0); + float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, state.get(FACING).getOpposite()) + ? context.getAnimationSpeed() + : 0); Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); float time = AnimationTickHolder.getRenderTick(); float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java index 007ed8d6e..8597a81f0 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java @@ -5,6 +5,7 @@ import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.block.IRenderUtilityBlock; import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VoxelShaper; import com.simibubi.create.modules.contraptions.receivers.contraptions.IHaveMovementBehavior; @@ -107,18 +108,25 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha } @Override - public void visitPosition(MovementContext context) { - Direction movement = context.getMovementDirection(); + public boolean isActive(MovementContext context) { + return !VecHelper.isVecPointingTowards(context.relativeMotion, + context.state.get(HORIZONTAL_FACING).getOpposite()); + } + + @Override + public Vec3d getActiveAreaOffset(MovementContext context) { + return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.5); + } + + @Override + public void visitNewPosition(MovementContext context, BlockPos pos) { World world = context.world; - BlockState block = context.state; - BlockPos pos = context.currentGridPos; - -// if (movement != block.get(HORIZONTAL_FACING)) -// return; - BlockState stateVisited = world.getBlockState(pos); boolean notCropButCuttable = false; + if (world.isRemote) + return; + if (stateVisited.getBlock() == Blocks.SUGAR_CANE) { notCropButCuttable = true; pos = pos.up(); @@ -143,8 +151,7 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha seedSubtracted = true; } ItemEntity itemEntity = new ItemEntity(world, pos.getX() + .5f, pos.getY() + .25f, pos.getZ() + .5f, stack); - itemEntity.setMotion( - new Vec3d(movement.getDirectionVec()).add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f)); + itemEntity.setMotion(context.motion.add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f)); world.addEntity(itemEntity); } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterTileEntityRenderer.java index 802cfa103..46bd892ec 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterTileEntityRenderer.java @@ -7,6 +7,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.modules.contraptions.receivers.contraptions.IHaveMovementBehavior.MovementContext; import net.minecraft.block.BlockState; @@ -28,13 +29,9 @@ public class HarvesterTileEntityRenderer extends TileEntityRenderer pair : actors) { - MovementContext context = new MovementContext(world, pair.left.state); - context.world = world; - context.motion = Vec3d.ZERO; - context.currentGridPos = BlockPos.ZERO; + BlockState blockState = pair.left.state; + MovementContext context = new MovementContext(world, blockState); + ((IHaveMovementBehavior) blockState.getBlock()).startMoving(context); pair.setRight(context); } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/ContraptionEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/ContraptionEntity.java index c7a23f07a..785644753 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/ContraptionEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/ContraptionEntity.java @@ -1,5 +1,7 @@ package com.simibubi.create.modules.contraptions.receivers.contraptions; +import org.apache.commons.lang3.tuple.MutablePair; + import com.simibubi.create.AllEntities; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.modules.contraptions.receivers.contraptions.IHaveMovementBehavior.MovementContext; @@ -11,25 +13,25 @@ import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.NBTUtil; import net.minecraft.network.IPacket; import net.minecraft.network.PacketBuffer; -import net.minecraft.particles.ParticleTypes; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.server.ServerWorld; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; import net.minecraftforge.fml.network.NetworkHooks; public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnData { - private Contraption contraption; + protected Contraption contraption; protected float initialAngle; - protected BlockPos controllerPos; protected IControlContraption controllerTE; + public float movementSpeedModifier; + public float prevYaw; public float prevPitch; public float prevRoll; @@ -57,6 +59,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD this.prevYaw = initialAngle; this.yaw = initialAngle; this.targetYaw = initialAngle; + movementSpeedModifier = 1; } public ContraptionEntity controlledBy(T controller) { @@ -82,11 +85,17 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD yaw += 360; } - float speed = 0.2f; - prevYaw = yaw; - yaw = angleLerp(speed, yaw, targetYaw); - prevPitch = pitch; - pitch = angleLerp(speed, pitch, targetPitch); + 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); + prevPitch = pitch; + pitch = angleLerp(speed, pitch, targetPitch); + } tickActors(movementVector); super.tick(); @@ -102,31 +111,48 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD } public void tickActors(Vec3d movementVector) { - getContraption().getActors().forEach(pair -> { + movementSpeedModifier = 1; + + float anglePitch = getPitch(1); + float angleYaw = getYaw(1); + float angleRoll = getRoll(1); + Vec3d rotationVec = new Vec3d(angleRoll, angleYaw, anglePitch); + Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO); + + for (MutablePair pair : contraption.actors) { MovementContext context = pair.right; - float deg = (getRidingEntity() != null ? yaw + 180 : yaw) + initialAngle; - context.motion = VecHelper.rotate(movementVector, deg, Axis.Y); + BlockInfo blockInfo = pair.left; + IHaveMovementBehavior actor = (IHaveMovementBehavior) blockInfo.state.getBlock(); - if (context.world == null) - context.world = world; + Vec3d actorPosition = new Vec3d(blockInfo.pos); + actorPosition = actorPosition.add(actor.getActiveAreaOffset(context)); + actorPosition = VecHelper.rotate(actorPosition, angleRoll, angleYaw, anglePitch); + actorPosition = actorPosition.add(rotationOffset).add(posX, posY, posZ); - Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO); - Vec3d offset = new Vec3d(pair.left.pos); - offset = VecHelper.rotate(offset, deg, Axis.Y); - offset = offset.add(rotationOffset); - offset = offset.add(posX, posY, posZ); + Vec3d previousPosition = context.position; + BlockPos gridPosition = new BlockPos(actorPosition); + boolean newPosVisited = true; - if (world.isRemote) - return; + if (previousPosition != null) { + context.motion = actorPosition.subtract(previousPosition); + Vec3d relativeMotion = context.motion; + relativeMotion = VecHelper.rotate(relativeMotion, -angleRoll, -angleYaw, -anglePitch); + context.relativeMotion = relativeMotion; + newPosVisited = !new BlockPos(previousPosition).equals(gridPosition); + } - BlockPos gridPos = new BlockPos(offset); - if (context.currentGridPos.equals(gridPos)) - return; - context.currentGridPos = gridPos; + context.rotation = rotationVec; + context.position = actorPosition; + + if (actor.isActive(context)) { + if (newPosVisited) + actor.visitNewPosition(context, gridPosition); + actor.tick(context); + } - IHaveMovementBehavior actor = (IHaveMovementBehavior) pair.left.state.getBlock(); - actor.visitPosition(context); - }); + if (movementSpeedModifier > context.movementSpeedModifier) + movementSpeedModifier = context.movementSpeedModifier; + } } public void moveTo(double x, double y, double z) { @@ -182,11 +208,12 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD } public static float yawFromMotion(Vec3d motion) { - return (float) ((Math.PI / 2 - Math.atan2(motion.z, motion.x)) / Math.PI * 180); + return (float) ((3 * Math.PI / 2 + Math.atan2(motion.z, motion.x)) / Math.PI * 180); } public float getYaw(float partialTicks) { - return (partialTicks == 1.0F ? yaw : angleLerp(partialTicks, prevYaw, yaw)) - initialAngle; + return (getRidingEntity() == null ? 1 : -1) + * (partialTicks == 1.0F ? yaw : angleLerp(partialTicks, prevYaw, yaw)) + initialAngle; } public float getPitch(float partialTicks) { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/ContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/ContraptionEntityRenderer.java index 630080cdb..88508e8fd 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/ContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/ContraptionEntityRenderer.java @@ -36,6 +36,13 @@ public class ContraptionEntityRenderer extends EntityRenderer return; GlStateManager.pushMatrix(); + long randomBits = (long) entity.getEntityId() * 493286711L; + randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L; + float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; + float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; + float zNudge = (((float) (randomBits >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; + GlStateManager.translatef(xNudge, yNudge, zNudge); + float angleYaw = (float) (entity.getYaw(partialTicks) / 180 * Math.PI); float anglePitch = (float) (entity.getPitch(partialTicks) / 180 * Math.PI); float angleRoll = (float) (entity.getRoll(partialTicks) / 180 * Math.PI); @@ -44,20 +51,12 @@ public class ContraptionEntityRenderer extends EntityRenderer if (ridingEntity != null && ridingEntity instanceof AbstractMinecartEntity) { AbstractMinecartEntity cart = (AbstractMinecartEntity) ridingEntity; - long i = (long) entity.getEntityId() * 493286711L; - i = i * i * 4392167121L + i * 98761L; - float f = (((float) (i >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - float f1 = (((float) (i >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - float f2 = (((float) (i >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - GlStateManager.translatef(f, f1, f2); - double cartX = MathHelper.lerp((double) partialTicks, cart.lastTickPosX, cart.posX); double cartY = MathHelper.lerp((double) partialTicks, cart.lastTickPosY, cart.posY); double cartZ = MathHelper.lerp((double) partialTicks, cart.lastTickPosZ, cart.posZ); Vec3d cartPos = cart.getPos(cartX, cartY, cartZ); if (cartPos != null) { - Vec3d cartPosFront = cart.getPosOffset(cartX, cartY, cartZ, (double) 0.3F); Vec3d cartPosBack = cart.getPosOffset(cartX, cartY, cartZ, (double) -0.3F); if (cartPosFront == null) @@ -73,10 +72,7 @@ public class ContraptionEntityRenderer extends EntityRenderer } } -// BlockPos anchor = entity.getContraption().getAnchor(); Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO); -// Vec3d offset = VecHelper.getCenterOf(anchor).scale(-1); - TessellatorHelper.prepareFastRender(); TessellatorHelper.begin(DefaultVertexFormats.BLOCK); ContraptionRenderer.render(entity.world, entity.getContraption(), superByteBuffer -> { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/IHaveMovementBehavior.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/IHaveMovementBehavior.java index b1f3a4137..6e179eb61 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/IHaveMovementBehavior.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/IHaveMovementBehavior.java @@ -2,12 +2,10 @@ package com.simibubi.create.modules.contraptions.receivers.contraptions; import com.simibubi.create.foundation.utility.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.modules.contraptions.receivers.contraptions.piston.MechanicalPistonTileEntity; import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.NBTUtil; -import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; @@ -17,60 +15,82 @@ import net.minecraftforge.common.util.Constants.NBT; public interface IHaveMovementBehavior { - public enum MoverType { - PISTON, BEARING, MINECART; - } - - default void visitPosition(MovementContext context) { - } - - default void tick(MechanicalPistonTileEntity piston) { - } - - default boolean hasSpecialRenderer() { - return false; - } - public class MovementContext { - public BlockPos currentGridPos; + public Vec3d position; public Vec3d motion; - public float movementSpeedModifier = 1; + public Vec3d relativeMotion; + public Vec3d rotation; public World world; public BlockState state; + public float movementSpeedModifier; + public CompoundNBT data; + public MovementContext(World world, BlockState state) { this.world = world; this.state = state; - } - public Direction getMovementDirection() { - return Direction.getFacingFromVector(motion.x, motion.y, motion.z); + motion = Vec3d.ZERO; + relativeMotion = Vec3d.ZERO; + rotation = Vec3d.ZERO; + position = null; + data = new CompoundNBT(); + movementSpeedModifier = 1; } public float getAnimationSpeed() { int modifier = 1000; - return ((int) (motion.length() * modifier)) / 100 * 100; + double length = -motion.length(); + if (Math.abs(length) < 1 / 512f) + return 0; + return (((int) (length * modifier + 100 * Math.signum(length))) / 100) * 100; } public static MovementContext readNBT(World world, CompoundNBT nbt) { - MovementContext context = new MovementContext(world, NBTUtil.readBlockState(nbt.getCompound("State"))); + BlockState state = NBTUtil.readBlockState(nbt.getCompound("State")); + MovementContext context = new MovementContext(world, state); context.motion = VecHelper.readNBT(nbt.getList("Motion", NBT.TAG_DOUBLE)); + context.relativeMotion = VecHelper.readNBT(nbt.getList("RelativeMotion", NBT.TAG_DOUBLE)); + context.rotation = VecHelper.readNBT(nbt.getList("Rotation", NBT.TAG_DOUBLE)); + if (nbt.contains("Position")) + context.position = VecHelper.readNBT(nbt.getList("Position", NBT.TAG_DOUBLE)); context.movementSpeedModifier = nbt.getFloat("SpeedModifier"); - context.currentGridPos = NBTUtil.readBlockPos(nbt.getCompound("GridPos")); + context.data = nbt.getCompound("Data"); return context; } public CompoundNBT writeToNBT(CompoundNBT nbt) { nbt.put("State", NBTUtil.writeBlockState(state)); nbt.put("Motion", VecHelper.writeNBT(motion)); + nbt.put("RelativeMotion", VecHelper.writeNBT(relativeMotion)); + nbt.put("Rotation", VecHelper.writeNBT(rotation)); + if (position != null) + nbt.put("Position", VecHelper.writeNBT(position)); nbt.putFloat("SpeedModifier", movementSpeedModifier); - nbt.put("GridPos", NBTUtil.writeBlockPos(currentGridPos)); + nbt.put("Data", data); return nbt; } } + default boolean isActive(MovementContext context) { + return true; + } + + default void tick(MovementContext context) { + } + + default void startMoving(MovementContext context) { + } + + default void visitNewPosition(MovementContext context, BlockPos pos) { + } + + default Vec3d getActiveAreaOffset(MovementContext context) { + return Vec3d.ZERO; + } + @OnlyIn(value = Dist.CLIENT) default SuperByteBuffer renderInContraption(MovementContext context) { return null; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/bearing/MechanicalBearingTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/bearing/MechanicalBearingTileEntity.java index c547e6487..cdfcf0780 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/bearing/MechanicalBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/contraptions/bearing/MechanicalBearingTileEntity.java @@ -170,7 +170,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp if (movedContraption != null) { Direction direction = getBlockState().get(BlockStateProperties.FACING); Vec3d vec = new Vec3d(1, 1, 1).scale(angle * 180 / Math.PI).mul(new Vec3d(direction.getDirectionVec())); - movedContraption.rotateTo(-vec.x, vec.y, -vec.z); + movedContraption.rotateTo(vec.x, vec.y, -vec.z); } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java index dba5d5b1c..9504035ec 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java @@ -4,6 +4,7 @@ import java.util.Random; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.block.ProperDirectionalBlock; +import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.modules.contraptions.receivers.contraptions.IHaveMovementBehavior; import net.minecraft.block.Block; @@ -15,6 +16,7 @@ import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorld; import net.minecraft.world.TickPriority; @@ -100,19 +102,32 @@ public class ContactBlock extends ProperDirectionalBlock implements IHaveMovemen } @Override - public void visitPosition(MovementContext context) { + public Vec3d getActiveAreaOffset(MovementContext context) { + return new Vec3d(context.state.get(FACING).getDirectionVec()).scale(.65f); + } + + @Override + public void visitNewPosition(MovementContext context, BlockPos pos) { BlockState block = context.state; World world = context.world; - BlockPos pos = context.currentGridPos; - Direction direction = block.get(FACING); - if (!hasValidContact(world, pos, direction)) + if (world.isRemote) return; - int ticksToStayActive = (int) Math - .ceil(1 / Math.abs(context.motion.length())); - world.setBlockState(pos.offset(direction), world.getBlockState(pos.offset(direction)).with(POWERED, true)); - world.getPendingBlockTicks().scheduleTick(pos.offset(direction), this, ticksToStayActive, TickPriority.NORMAL); + BlockState visitedState = world.getBlockState(pos); + if (!AllBlocks.CONTACT.typeOf(visitedState)) + return; + + Vec3d contact = new Vec3d(block.get(FACING).getDirectionVec()); + contact = VecHelper.rotate(contact, context.rotation.x, context.rotation.y, context.rotation.z); + Direction direction = Direction.getFacingFromVector(contact.x, contact.y, contact.z); + + if (!hasValidContact(world, pos.offset(direction.getOpposite()), direction)) + return; + + int ticksToStayActive = 4; + world.setBlockState(pos, visitedState.with(POWERED, true)); + world.getPendingBlockTicks().scheduleTick(pos, this, ticksToStayActive, TickPriority.NORMAL); return; }