mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-25 06:26:56 +01:00
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)
This commit is contained in:
parent
f991c88fc2
commit
5db014c45b
11 changed files with 188 additions and 110 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<HarvesterTil
|
|||
|
||||
public static SuperByteBuffer renderInContraption(MovementContext context) {
|
||||
BlockState state = context.state;
|
||||
Direction facing = context.getMovementDirection();
|
||||
float speed = -500 * state.get(HORIZONTAL_FACING).getAxisDirection().getOffset();
|
||||
// float speed = (float) (facing != state.get(HORIZONTAL_FACING)
|
||||
// ? context.getAnimationSpeed() * facing.getAxisDirection().getOffset()
|
||||
// : 0);
|
||||
// if (facing.getAxis() == Axis.X)
|
||||
// speed = -speed;
|
||||
float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, state.get(HORIZONTAL_FACING).getOpposite())
|
||||
? context.getAnimationSpeed() * state.get(HORIZONTAL_FACING).getAxisDirection().getOffset()
|
||||
: 0);
|
||||
float time = AnimationTickHolder.getRenderTick();
|
||||
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@ import net.minecraft.util.Direction.Axis;
|
|||
import net.minecraft.util.Direction.AxisDirection;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||
|
@ -597,10 +596,9 @@ public class Contraption {
|
|||
|
||||
public void initActors(World world) {
|
||||
for (MutablePair<BlockInfo, MovementContext> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <T extends TileEntity & IControlContraption> 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<BlockInfo, MovementContext> 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) {
|
||||
|
|
|
@ -36,6 +36,13 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
|
|||
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<ContraptionEntity>
|
|||
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<ContraptionEntity>
|
|||
}
|
||||
}
|
||||
|
||||
// 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 -> {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue