Seats, part II

- Any living entity can now use seats
- Fix client sync issues with seats
- Fixed contraptions double-reversing roll and pitch values when communicating to the collision engine
- Seats now transfer their passengers to a contraption when moved and back when disassembled
- Attempted further refinements to the collision response of horizontally rotated contraptions
- Set up a hook to inject custom interaction between players and contraption mounted blocks on right-click
- Seats can now by mounted by players while assembled to a contraption
- Minor refactors to the contraption class
This commit is contained in:
simibubi 2020-07-22 01:18:09 +02:00
parent d3e7b23d6e
commit 7994835cb0
35 changed files with 1231 additions and 705 deletions

View file

@ -0,0 +1,89 @@
import org.apache.commons.lang3.mutable.MutableObject;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionInteractionPacket;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.RaycastHelper;
import com.simibubi.create.foundation.utility.RaycastHelper.PredicateTraceResult;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.event.InputEvent.ClickInputEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class ContraptionInteractionHandler {
@SubscribeEvent
@OnlyIn(Dist.CLIENT)
public static void rightClickingOnContraptionsGetsHandledLocally(ClickInputEvent event) {
Minecraft mc = Minecraft.getInstance();
ClientPlayerEntity player = mc.player;
if (player == null)
return;
if (mc.world == null)
return;
if (!event.isUseItem())
return;
Vec3d origin = RaycastHelper.getTraceOrigin(player);
double reach = mc.playerController.getBlockReachDistance();
if (mc.objectMouseOver != null && mc.objectMouseOver.getHitVec() != null)
reach = Math.min(mc.objectMouseOver.getHitVec().distanceTo(origin), reach);
Vec3d target = RaycastHelper.getTraceTarget(player, reach, origin);
for (ContraptionEntity contraptionEntity : mc.world.getEntitiesWithinAABB(ContraptionEntity.class,
new AxisAlignedBB(origin, target))) {
Vec3d localOrigin = contraptionEntity.toLocalVector(origin);
Vec3d localTarget = contraptionEntity.toLocalVector(target);
Contraption contraption = contraptionEntity.getContraption();
MutableObject<BlockRayTraceResult> mutableResult = new MutableObject<>();
PredicateTraceResult predicateResult = RaycastHelper.rayTraceUntil(localOrigin, localTarget, p -> {
BlockInfo blockInfo = contraption.blocks.get(p);
if (blockInfo == null)
return false;
BlockState state = blockInfo.state;
VoxelShape raytraceShape = state.getShape(Minecraft.getInstance().world, BlockPos.ZERO.down());
if (raytraceShape.isEmpty())
return false;
BlockRayTraceResult rayTrace = raytraceShape.rayTrace(localOrigin, localTarget, p);
if (rayTrace != null) {
mutableResult.setValue(rayTrace);
return true;
}
return false;
});
if (predicateResult == null || predicateResult.missed())
return;
BlockRayTraceResult rayTraceResult = mutableResult.getValue();
Hand hand = event.getHand();
Direction face = rayTraceResult.getFace();
BlockPos pos = rayTraceResult.getPos();
if (!contraptionEntity.handlePlayerInteraction(player, pos, face, hand))
return;
AllPackets.channel.sendToServer(new ContraptionInteractionPacket(contraptionEntity, hand,
pos, face));
event.setCanceled(true);
event.setSwingHand(false);
}
}
}

View file

@ -26,7 +26,7 @@ public class AllEntityTypes {
public static final RegistryEntry<EntityType<SuperGlueEntity>> SUPER_GLUE = public static final RegistryEntry<EntityType<SuperGlueEntity>> SUPER_GLUE =
register("super_glue", SuperGlueEntity::new, EntityClassification.MISC, 10, Integer.MAX_VALUE, false, SuperGlueEntity::build); register("super_glue", SuperGlueEntity::new, EntityClassification.MISC, 10, Integer.MAX_VALUE, false, SuperGlueEntity::build);
public static final RegistryEntry<EntityType<SeatEntity>> SEAT = public static final RegistryEntry<EntityType<SeatEntity>> SEAT =
register("seat", SeatEntity::new, EntityClassification.MISC, 0, Integer.MAX_VALUE, false, SeatEntity::build); register("seat", SeatEntity::new, EntityClassification.MISC, 5, Integer.MAX_VALUE, false, SeatEntity::build);
private static <T extends Entity> RegistryEntry<EntityType<T>> register(String name, IFactory<T> factory, private static <T extends Entity> RegistryEntry<EntityType<T>> register(String name, IFactory<T> factory,
EntityClassification group, int range, int updateFrequency, boolean sendVelocity, EntityClassification group, int range, int updateFrequency, boolean sendVelocity,

View file

@ -1,17 +1,25 @@
package com.simibubi.create.content.contraptions.components.actors; package com.simibubi.create.content.contraptions.components.actors;
import java.util.List;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.components.structureMovement.IPortableBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MobEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
@ -19,15 +27,16 @@ import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class SeatBlock extends Block { public class SeatBlock extends Block implements IPortableBlock {
public static MovementBehaviour MOVEMENT = new SeatMovementBehaviour();
private boolean inCreativeTab; private boolean inCreativeTab;
public SeatBlock(Properties p_i48440_1_, boolean inCreativeTab) { public SeatBlock(Properties p_i48440_1_, boolean inCreativeTab) {
super(p_i48440_1_); super(p_i48440_1_);
this.inCreativeTab = inCreativeTab; this.inCreativeTab = inCreativeTab;
} }
@Override @Override
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> p_149666_2_) { public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> p_149666_2_) {
if (group != ItemGroup.SEARCH && !inCreativeTab) if (group != ItemGroup.SEARCH && !inCreativeTab)
@ -41,8 +50,21 @@ public class SeatBlock extends Block {
} }
@Override @Override
public void onLanded(IBlockReader p_176216_1_, Entity p_176216_2_) { public void onLanded(IBlockReader reader, Entity entity) {
Blocks.PINK_BED.onLanded(p_176216_1_, p_176216_2_); BlockPos pos = entity.getPosition();
if (entity instanceof PlayerEntity || !(entity instanceof LivingEntity) || isSeatOccupied(entity.world, pos)) {
Blocks.PINK_BED.onLanded(reader, entity);
return;
}
if (reader.getBlockState(pos)
.getBlock() != this)
return;
sitDown(entity.world, pos, entity);
}
@Override
public PathNodeType getAiPathNodeType(BlockState state, IBlockReader world, BlockPos pos, MobEntity entity) {
return PathNodeType.RAIL;
} }
@Override @Override
@ -52,17 +74,46 @@ public class SeatBlock extends Block {
} }
@Override @Override
public ActionResultType onUse(BlockState p_225533_1_, World world, BlockPos pos, PlayerEntity player, Hand p_225533_5_, BlockRayTraceResult p_225533_6_) { public ActionResultType onUse(BlockState p_225533_1_, World world, BlockPos pos, PlayerEntity player,
if (SeatEntity.TAKEN.containsKey(pos)) Hand p_225533_5_, BlockRayTraceResult p_225533_6_) {
return ActionResultType.FAIL; if (player.isSneaking())
return ActionResultType.PASS;
List<SeatEntity> seats = world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos));
if (!seats.isEmpty()) {
SeatEntity seatEntity = seats.get(0);
List<Entity> passengers = seatEntity.getPassengers();
if (!passengers.isEmpty() && passengers.get(0) instanceof PlayerEntity)
return ActionResultType.PASS;
if (!world.isRemote) {
seatEntity.removePassengers();
player.startRiding(seatEntity);
}
return ActionResultType.SUCCESS;
}
if (world.isRemote) if (world.isRemote)
return ActionResultType.SUCCESS; return ActionResultType.SUCCESS;
sitDown(world, pos, player);
SeatEntity seat = new SeatEntity(world, pos);
world.addEntity(seat);
player.startRiding(seat);
return ActionResultType.SUCCESS; return ActionResultType.SUCCESS;
} }
public static boolean isSeatOccupied(World world, BlockPos pos) {
return !world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos))
.isEmpty();
}
public static void sitDown(World world, BlockPos pos, Entity entity) {
if (world.isRemote)
return;
SeatEntity seat = new SeatEntity(world, pos);
seat.setPos(pos.getX() + .5f, pos.getY(), pos.getZ() + .5f);
world.addEntity(seat);
entity.startRiding(seat, true);
}
@Override
public MovementBehaviour getMovementBehaviour() {
return MOVEMENT;
}
} }

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.contraptions.components.actors; package com.simibubi.create.content.contraptions.components.actors;
import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllEntityTypes;
import net.minecraft.client.renderer.culling.ClippingHelperImpl; import net.minecraft.client.renderer.culling.ClippingHelperImpl;
import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.client.renderer.entity.EntityRendererManager;
@ -8,18 +9,16 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.IPacket; import net.minecraft.network.IPacket;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.fml.network.NetworkHooks;
import java.util.HashMap; public class SeatEntity extends Entity implements IEntityAdditionalSpawnData {
import java.util.Map;
public class SeatEntity extends Entity {
public static final Map<BlockPos, SeatEntity> TAKEN = new HashMap<>();
public SeatEntity(EntityType<?> p_i48580_1_, World p_i48580_2_) { public SeatEntity(EntityType<?> p_i48580_1_, World p_i48580_2_) {
super(p_i48580_1_, p_i48580_2_); super(p_i48580_1_, p_i48580_2_);
@ -27,28 +26,39 @@ public class SeatEntity extends Entity {
public SeatEntity(World world, BlockPos pos) { public SeatEntity(World world, BlockPos pos) {
this(AllEntityTypes.SEAT.get(), world); this(AllEntityTypes.SEAT.get(), world);
this.setPos(pos.getX() + 0.5, pos.getY() + 0.30, pos.getZ() + 0.5);
noClip = true; noClip = true;
TAKEN.put(pos, this);
} }
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) { public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
EntityType.Builder<SeatEntity> entityBuilder = (EntityType.Builder<SeatEntity>) builder; EntityType.Builder<SeatEntity> entityBuilder = (EntityType.Builder<SeatEntity>) builder;
return entityBuilder.size(0, 0); return entityBuilder.size(0.25f, 0.35f);
} }
@Override
public AxisAlignedBB getBoundingBox() {
return super.getBoundingBox();
}
@Override
public void setPos(double x, double y, double z) {
super.setPos(x, y, z);
AxisAlignedBB bb = getBoundingBox();
Vec3d diff = new Vec3d(x, y, z).subtract(bb.getCenter());
setBoundingBox(bb.offset(diff));
}
@Override
public void setMotion(Vec3d p_213317_1_) {}
@Override @Override
public void tick() { public void tick() {
if (world.isRemote) if (world.isRemote)
return; return;
boolean blockPresent = world.getBlockState(getPosition())
BlockPos blockPos = new BlockPos(getX(), getY(), getZ()); .getBlock() instanceof SeatBlock;
if (isBeingRidden() && world.getBlockState(blockPos).getBlock() instanceof SeatBlock) if (isBeingRidden() && blockPresent)
return; return;
TAKEN.remove(blockPos);
this.remove(); this.remove();
} }
@ -61,7 +71,7 @@ public class SeatEntity extends Entity {
protected void removePassenger(Entity entity) { protected void removePassenger(Entity entity) {
super.removePassenger(entity); super.removePassenger(entity);
Vec3d pos = entity.getPositionVec(); Vec3d pos = entity.getPositionVec();
entity.setPosition(pos.x, pos.y + 0.7, pos.z); entity.setPosition(pos.x, pos.y + 0.85f, pos.z);
} }
@Override @Override
@ -85,7 +95,8 @@ public class SeatEntity extends Entity {
} }
@Override @Override
public boolean shouldRender(SeatEntity p_225626_1_, ClippingHelperImpl p_225626_2_, double p_225626_3_, double p_225626_5_, double p_225626_7_) { public boolean shouldRender(SeatEntity p_225626_1_, ClippingHelperImpl p_225626_2_, double p_225626_3_,
double p_225626_5_, double p_225626_7_) {
return false; return false;
} }
@ -94,4 +105,10 @@ public class SeatEntity extends Entity {
return null; return null;
} }
} }
@Override
public void writeSpawnData(PacketBuffer buffer) {}
@Override
public void readSpawnData(PacketBuffer additionalData) {}
} }

View file

@ -0,0 +1,9 @@
package com.simibubi.create.content.contraptions.components.actors;
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
public class SeatMovementBehaviour extends MovementBehaviour {
}

View file

@ -24,6 +24,7 @@ import com.simibubi.create.foundation.collision.ContinuousOBBCollider.Continuous
import com.simibubi.create.foundation.collision.Matrix3d; import com.simibubi.create.foundation.collision.Matrix3d;
import com.simibubi.create.foundation.collision.OrientedBB; import com.simibubi.create.foundation.collision.OrientedBB;
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -32,9 +33,11 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MoverType; import net.minecraft.entity.MoverType;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.DamageSource; import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
@ -51,10 +54,12 @@ import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.event.TickEvent.ClientTickEvent; import net.minecraftforge.event.TickEvent.ClientTickEvent;
import net.minecraftforge.event.TickEvent.Phase; import net.minecraftforge.event.TickEvent.Phase;
import net.minecraftforge.event.TickEvent.WorldTickEvent; import net.minecraftforge.event.TickEvent.WorldTickEvent;
import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@ -66,7 +71,7 @@ public class ContraptionCollider {
new DamageSource("create.contraption_suffocate").setDamageBypassesArmor(); new DamageSource("create.contraption_suffocate").setDamageBypassesArmor();
public static boolean wasClientPlayerGrounded; public static boolean wasClientPlayerGrounded;
public static Cache<World, List<WeakReference<ContraptionEntity>>> activeContraptions = CacheBuilder.newBuilder() public static Cache<World, List<WeakReference<ContraptionEntity>>> activeContraptions = CacheBuilder.newBuilder()
.expireAfterAccess(40, SECONDS) .expireAfterAccess(400, SECONDS)
.build(); .build();
@SubscribeEvent @SubscribeEvent
@ -102,6 +107,22 @@ public class ContraptionCollider {
runCollisions(world); runCollisions(world);
} }
@SubscribeEvent
public static void entitiesWhoJustDismountedGetSentToTheRightLocation(LivingUpdateEvent event) {
LivingEntity entityLiving = event.getEntityLiving();
if (entityLiving == null)
return;
if (entityLiving.world.isRemote)
return;
CompoundNBT data = entityLiving.getPersistentData();
if (!data.contains("ContraptionDismountLocation"))
return;
Vec3d position = VecHelper.readNBT(data.getList("ContraptionDismountLocation", NBT.TAG_DOUBLE));
if (entityLiving.getRidingEntity() == null)
entityLiving.setPositionAndUpdate(position.x, position.y, position.z);
data.remove("ContraptionDismountLocation");
}
private static void runCollisions(World world) { private static void runCollisions(World world) {
List<WeakReference<ContraptionEntity>> list = activeContraptions.getIfPresent(world); List<WeakReference<ContraptionEntity>> list = activeContraptions.getIfPresent(world);
if (list == null) if (list == null)
@ -131,9 +152,9 @@ public class ContraptionCollider {
return; return;
Vec3d centerOfBlock = VecHelper.getCenterOf(BlockPos.ZERO); Vec3d centerOfBlock = VecHelper.getCenterOf(BlockPos.ZERO);
double conRotX = contraptionRotation.z; double conRotX = contraptionRotation.x;
double conRotY = contraptionRotation.y; double conRotY = contraptionRotation.y;
double conRotZ = contraptionRotation.x; double conRotZ = contraptionRotation.z;
Vec3d conMotion = contraptionPosition.subtract(contraptionEntity.getPrevPositionVec()); Vec3d conMotion = contraptionPosition.subtract(contraptionEntity.getPrevPositionVec());
Vec3d conAngularMotion = contraptionRotation.subtract(contraptionEntity.getPrevRotationVec()); Vec3d conAngularMotion = contraptionRotation.subtract(contraptionEntity.getPrevRotationVec());
Vec3d contraptionCentreOffset = contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0); Vec3d contraptionCentreOffset = contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0);
@ -180,6 +201,7 @@ public class ContraptionCollider {
// Prepare entity bounds // Prepare entity bounds
OrientedBB obb = new OrientedBB(localBB); OrientedBB obb = new OrientedBB(localBB);
obb.setRotation(rotation); obb.setRotation(rotation);
motion = motion.subtract(conMotion);
motion = rotation.transform(motion); motion = rotation.transform(motion);
// Vec3d visualizerOrigin = new Vec3d(10, 64, 0); // Vec3d visualizerOrigin = new Vec3d(10, 64, 0);
@ -198,41 +220,48 @@ public class ContraptionCollider {
.forEach(shape -> shape.toBoundingBoxList() .forEach(shape -> shape.toBoundingBoxList()
.forEach(bbs::add)); .forEach(bbs::add));
for (AxisAlignedBB bb : bbs) { boolean doHorizontalPass = conRotX == 0 && conRotZ == 0;
Vec3d currentResponse = collisionResponse.getValue(); for (boolean horizontalPass : Iterate.trueAndFalse) {
obb.setCenter(obbCenter.add(currentResponse));
ContinuousSeparationManifold intersect = obb.intersect(bb, allowedMotion.getValue());
// OutlineParams params = CreateClient.outliner.showAABB(bb, bb.offset(visualizerOrigin))
// .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED);
// params.colored(0xffffff);
if (intersect == null) for (AxisAlignedBB bb : bbs) {
continue; Vec3d currentResponse = collisionResponse.getValue();
if (surfaceCollision.isFalse()) obb.setCenter(obbCenter.add(currentResponse));
surfaceCollision.setValue(intersect.isSurfaceCollision()); ContinuousSeparationManifold intersect = obb.intersect(bb, allowedMotion.getValue());
double timeOfImpact = intersect.getTimeOfImpact(); if (intersect == null)
if (timeOfImpact > 0 && timeOfImpact < 1) { continue;
futureCollision.setTrue(); if ((!horizontalPass || !doHorizontalPass) && surfaceCollision.isFalse())
// Vec3d prev = allowedMotion.getValue(); surfaceCollision.setValue(intersect.isSurfaceCollision());
allowedMotion.setValue(intersect.getAllowedMotion(allowedMotion.getValue()));
// Debug.debugChat("Allowed Motion FROM " + prev.toString()); double timeOfImpact = intersect.getTimeOfImpact();
// Debug.debugChat("Allowed Motion TO " + allowedMotion.getValue() if (timeOfImpact > 0 && timeOfImpact < 1) {
// .toString()); futureCollision.setTrue();
// params.colored(0x4499ff); allowedMotion.setValue(intersect.getAllowedMotion(allowedMotion.getValue()));
continue; continue;
} }
Vec3d separation = intersect.asSeparationVec(entity.stepHeight);
if (separation != null && !separation.equals(Vec3d.ZERO)) { Vec3d separation = intersect.asSeparationVec(entity.stepHeight);
collisionResponse.setValue(currentResponse.add(separation)); if (separation != null && !separation.equals(Vec3d.ZERO))
// Debug.debugChat("Collision " + currentResponse.add(separation) collisionResponse.setValue(currentResponse.add(separation));
// .toString());
// params.colored(0xff9944);
} }
if (!horizontalPass || !doHorizontalPass)
break;
boolean noVerticalMotionResponse = allowedMotion.getValue().y == motion.y;
boolean noVerticalCollision = collisionResponse.getValue().y == 0;
if (noVerticalCollision && noVerticalMotionResponse)
break;
// Re-run collisions with horizontal offset
collisionResponse.setValue(collisionResponse.getValue()
.mul(1, 0, 1));
allowedMotion.setValue(allowedMotion.getValue()
.mul(1, 0, 1)
.add(0, motion.y, 0));
continue;
} }
// Debug.debugChat("----");
// Resolve collision // Resolve collision
Vec3d entityMotion = entity.getMotion(); Vec3d entityMotion = entity.getMotion();
Vec3d totalResponse = collisionResponse.getValue(); Vec3d totalResponse = collisionResponse.getValue();
@ -240,7 +269,8 @@ public class ContraptionCollider {
boolean hardCollision = !totalResponse.equals(Vec3d.ZERO); boolean hardCollision = !totalResponse.equals(Vec3d.ZERO);
rotation.transpose(); rotation.transpose();
motionResponse = rotation.transform(motionResponse); motionResponse = rotation.transform(motionResponse)
.add(conMotion);
totalResponse = rotation.transform(totalResponse); totalResponse = rotation.transform(totalResponse);
rotation.transpose(); rotation.transpose();
@ -262,7 +292,7 @@ public class ContraptionCollider {
Vec3d contactPoint = entityPosition.subtract(contraptionCentreOffset) Vec3d contactPoint = entityPosition.subtract(contraptionCentreOffset)
.subtract(contraptionPosition); .subtract(contraptionPosition);
contactPoint = contactPoint =
VecHelper.rotate(contactPoint, conAngularMotion.z, conAngularMotion.y, conAngularMotion.x); VecHelper.rotate(contactPoint, conAngularMotion.x, conAngularMotion.y, conAngularMotion.z);
contactPoint = contactPoint.add(contraptionPosition) contactPoint = contactPoint.add(contraptionPosition)
.add(contraptionCentreOffset) .add(contraptionCentreOffset)
.add(conMotion); .add(conMotion);

View file

@ -5,12 +5,15 @@ import static com.simibubi.create.foundation.utility.AngleHelper.getShortestAngl
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.MutablePair;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllEntityTypes;
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingContraption; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode;
@ -45,6 +48,7 @@ import net.minecraft.tags.BlockTags;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.DamageSource; import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.ReuseableStream; import net.minecraft.util.ReuseableStream;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -70,7 +74,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
protected BlockPos controllerPos; protected BlockPos controllerPos;
protected Vec3d motionBeforeStall; protected Vec3d motionBeforeStall;
protected boolean stationary; protected boolean stationary;
protected boolean initialized;
final List<Entity> collidingEntities = new ArrayList<>(); final List<Entity> collidingEntities = new ArrayList<>();
private static final Ingredient FUEL_ITEMS = Ingredient.fromItems(Items.COAL, Items.CHARCOAL); private static final Ingredient FUEL_ITEMS = Ingredient.fromItems(Items.COAL, Items.CHARCOAL);
@ -98,11 +102,9 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle) { public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle) {
ContraptionEntity entity = new ContraptionEntity(AllEntityTypes.CONTRAPTION.get(), world); ContraptionEntity entity = new ContraptionEntity(AllEntityTypes.CONTRAPTION.get(), world);
entity.contraption = contraption; entity.contraptionCreated(contraption);
entity.initialAngle = initialAngle; entity.initialAngle = initialAngle;
entity.forceYaw(initialAngle); entity.forceYaw(initialAngle);
if (contraption != null)
contraption.gatherStoredItems();
return entity; return entity;
} }
@ -116,12 +118,25 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
public static ContraptionEntity createStationary(World world, Contraption contraption) { public static ContraptionEntity createStationary(World world, Contraption contraption) {
ContraptionEntity entity = new ContraptionEntity(AllEntityTypes.STATIONARY_CONTRAPTION.get(), world); ContraptionEntity entity = new ContraptionEntity(AllEntityTypes.STATIONARY_CONTRAPTION.get(), world);
entity.contraption = contraption; entity.contraptionCreated(contraption);
if (contraption != null)
contraption.gatherStoredItems();
return entity; return entity;
} }
protected void contraptionCreated(Contraption contraption) {
this.contraption = contraption;
if (contraption == null)
return;
if (world.isRemote)
return;
contraption.gatherStoredItems();
}
protected void contraptionInitialize() {
if (!world.isRemote)
contraption.mountPassengers(this);
initialized = true;
}
public <T extends TileEntity & IControlContraption> ContraptionEntity controlledBy(T controller) { public <T extends TileEntity & IControlContraption> ContraptionEntity controlledBy(T controller) {
this.controllerPos = controller.getPos(); this.controllerPos = controller.getPos();
return this; return this;
@ -142,6 +157,110 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
return true; return true;
} }
@Override
protected void addPassenger(Entity passenger) {
super.addPassenger(passenger);
}
public void addSittingPassenger(Entity passenger, int seatIndex) {
passenger.startRiding(this, true);
if (world.isRemote)
return;
contraption.seatMapping.put(passenger.getUniqueID(), seatIndex);
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
new ContraptionSeatMappingPacket(getEntityId(), contraption.seatMapping));
}
@Override
protected void removePassenger(Entity passenger) {
Vec3d transformedVector = getPassengerPosition(passenger);
super.removePassenger(passenger);
if (world.isRemote)
return;
if (transformedVector != null)
passenger.getPersistentData()
.put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector));
contraption.seatMapping.remove(passenger.getUniqueID());
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
new ContraptionSeatMappingPacket(getEntityId(), contraption.seatMapping));
}
@Override
public void updatePassengerPosition(Entity passenger, IMoveCallback callback) {
if (!isPassenger(passenger))
return;
Vec3d transformedVector = getPassengerPosition(passenger);
if (transformedVector == null)
return;
callback.accept(passenger, transformedVector.x, transformedVector.y, transformedVector.z);
}
protected Vec3d getPassengerPosition(Entity passenger) {
AxisAlignedBB bb = passenger.getBoundingBox();
double ySize = bb.getYSize();
BlockPos seat = contraption.getSeat(passenger.getUniqueID());
if (seat == null)
return null;
Vec3d transformedVector = toGlobalVector(new Vec3d(seat).add(.5, passenger.getYOffset() + ySize - .15f, .5))
.add(VecHelper.getCenterOf(BlockPos.ZERO))
.subtract(0.5, ySize, 0.5);
return transformedVector;
}
@Override
protected boolean canFitPassenger(Entity p_184219_1_) {
return getPassengers().size() < contraption.seats.size();
}
public boolean handlePlayerInteraction(PlayerEntity player, BlockPos localPos, Direction side,
Hand interactionHand) {
int indexOfSeat = contraption.seats.indexOf(localPos);
if (indexOfSeat == -1)
return false;
// Eject potential existing passenger
for (Entry<UUID, Integer> entry : contraption.seatMapping.entrySet()) {
if (entry.getValue() != indexOfSeat)
continue;
for (Entity entity : getPassengers()) {
if (!entry.getKey().equals(entity.getUniqueID()))
continue;
if (entity instanceof PlayerEntity)
return false;
if (!world.isRemote) {
Vec3d transformedVector = getPassengerPosition(entity);
entity.stopRiding();
if (transformedVector != null)
entity.setPositionAndUpdate(transformedVector.x, transformedVector.y, transformedVector.z);
}
}
}
if (world.isRemote)
return true;
addSittingPassenger(player, indexOfSeat);
return true;
}
public Vec3d toGlobalVector(Vec3d localVec) {
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
localVec = localVec.subtract(rotationOffset);
localVec = VecHelper.rotate(localVec, getRotationVec());
localVec = localVec.add(rotationOffset)
.add(getAnchorVec());
return localVec;
}
public Vec3d toLocalVector(Vec3d globalVec) {
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
globalVec = globalVec.subtract(getAnchorVec())
.subtract(rotationOffset);
globalVec = VecHelper.rotate(globalVec, getRotationVec().scale(-1));
globalVec = globalVec.add(rotationOffset);
return globalVec;
}
@Override @Override
public void tick() { public void tick() {
if (contraption == null) { if (contraption == null) {
@ -149,6 +268,9 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
return; return;
} }
if (!initialized)
contraptionInitialize();
checkController(); checkController();
Entity mountedEntity = getRidingEntity(); Entity mountedEntity = getRidingEntity();
@ -173,10 +295,6 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
super.tick(); super.tick();
} }
public void collisionTick() {
// ContraptionCollider.collideEntities(this);
}
public void tickAsPassenger(Entity e) { public void tickAsPassenger(Entity e) {
boolean rotationLock = false; boolean rotationLock = false;
boolean pauseWhileRotating = false; boolean pauseWhileRotating = false;
@ -266,10 +384,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
public void tickActors(Vec3d movementVector) { public void tickActors(Vec3d movementVector) {
float anglePitch = getPitch(1); Vec3d rotationVec = getRotationVec();
float angleYaw = getYaw(1); Vec3d reversedRotationVec = rotationVec.scale(-1);
float angleRoll = getRoll(1);
Vec3d rotationVec = new Vec3d(angleRoll, angleYaw, anglePitch);
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO); Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
boolean stalledPreviously = contraption.stalled; boolean stalledPreviously = contraption.stalled;
@ -283,7 +399,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
Vec3d actorPosition = new Vec3d(blockInfo.pos); Vec3d actorPosition = new Vec3d(blockInfo.pos);
actorPosition = actorPosition.add(actor.getActiveAreaOffset(context)); actorPosition = actorPosition.add(actor.getActiveAreaOffset(context));
actorPosition = VecHelper.rotate(actorPosition, angleRoll, angleYaw, anglePitch); actorPosition = VecHelper.rotate(actorPosition, rotationVec);
actorPosition = actorPosition.add(rotationOffset) actorPosition = actorPosition.add(rotationOffset)
.add(getAnchorVec()); .add(getAnchorVec());
@ -295,7 +411,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (previousPosition != null) { if (previousPosition != null) {
context.motion = actorPosition.subtract(previousPosition); context.motion = actorPosition.subtract(previousPosition);
Vec3d relativeMotion = context.motion; Vec3d relativeMotion = context.motion;
relativeMotion = VecHelper.rotate(relativeMotion, -angleRoll, -angleYaw, -anglePitch); relativeMotion = VecHelper.rotate(relativeMotion, reversedRotationVec);
context.relativeMotion = relativeMotion; context.relativeMotion = relativeMotion;
newPosVisited = !new BlockPos(previousPosition).equals(gridPosition) newPosVisited = !new BlockPos(previousPosition).equals(gridPosition)
|| context.relativeMotion.length() > 0 && context.firstMovement; || context.relativeMotion.length() > 0 && context.firstMovement;
@ -429,6 +545,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
@Override @Override
protected void readAdditional(CompoundNBT compound) { protected void readAdditional(CompoundNBT compound) {
initialized = compound.getBoolean("Initialized");
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption")); contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
initialAngle = compound.getFloat("InitialAngle"); initialAngle = compound.getFloat("InitialAngle");
forceYaw(compound.contains("ForcedYaw") ? compound.getFloat("ForcedYaw") : initialAngle); forceYaw(compound.contains("ForcedYaw") ? compound.getFloat("ForcedYaw") : initialAngle);
@ -479,6 +596,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
compound.putFloat("InitialAngle", initialAngle); compound.putFloat("InitialAngle", initialAngle);
compound.putBoolean("Stalled", isStalled()); compound.putBoolean("Stalled", isStalled());
compound.putBoolean("Initialized", initialized);
} }
@Override @Override
@ -499,15 +617,15 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
public void disassemble() { public void disassemble() {
if (!isAlive()) { if (!isAlive())
return; return;
}
if (getContraption() != null) { if (getContraption() != null) {
remove(); remove();
BlockPos offset = new BlockPos(getAnchorVec().add(.5, .5, .5)); BlockPos offset = new BlockPos(getAnchorVec().add(.5, .5, .5));
Vec3d rotation = new Vec3d(getRoll(1), getYaw(1), getPitch(1)); Vec3d rotation = getRotationVec();
getContraption().addBlocksToWorld(world, offset, rotation); setBoundingBox(new AxisAlignedBB(0, 300, 0, 0, 300, 0));
preventMovedEntitiesFromGettingStuck(); contraption.addBlocksToWorld(world, offset, rotation, getPassengers());
// preventMovedEntitiesFromGettingStuck();
} }
} }
@ -633,11 +751,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
public Vec3d getRotationVec() { public Vec3d getRotationVec() {
return new Vec3d(getPitch(1), getYaw(1), getRoll(1)); return new Vec3d(getRoll(1), getYaw(1), getPitch(1));
} }
public Vec3d getPrevRotationVec() { public Vec3d getPrevRotationVec() {
return new Vec3d(getPitch(0), getYaw(0), getRoll(0)); return new Vec3d(getRoll(0), getYaw(0), getPitch(0));
} }
public Vec3d getPrevPositionVec() { public Vec3d getPrevPositionVec() {
@ -653,8 +771,12 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
return false; return false;
if (e instanceof SuperGlueEntity) if (e instanceof SuperGlueEntity)
return false; return false;
if (e instanceof SeatEntity)
return false;
if (e instanceof IProjectile) if (e instanceof IProjectile)
return false; return false;
if (e.getRidingEntity() != null)
return false;
Entity riding = this.getRidingEntity(); Entity riding = this.getRidingEntity();
while (riding != null) { while (riding != null) {

View file

@ -0,0 +1,65 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.network.NetworkEvent.Context;
public class ContraptionInteractionPacket extends SimplePacketBase {
private Hand interactionHand;
private int target;
private BlockPos localPos;
private Direction face;
public ContraptionInteractionPacket(ContraptionEntity target, Hand hand, BlockPos localPos, Direction side) {
this.interactionHand = hand;
this.localPos = localPos;
this.target = target.getEntityId();
this.face = side;
}
public ContraptionInteractionPacket(PacketBuffer buffer) {
target = buffer.readInt();
int handId = buffer.readInt();
interactionHand = handId == -1 ? null : Hand.values()[handId];
localPos = buffer.readBlockPos();
face = Direction.byIndex(buffer.readShort());
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeInt(target);
buffer.writeInt(interactionHand == null ? -1 : interactionHand.ordinal());
buffer.writeBlockPos(localPos);
buffer.writeShort(face.getIndex());
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
ServerPlayerEntity sender = context.get()
.getSender();
if (sender == null)
return;
Entity entityByID = sender.getServerWorld()
.getEntityByID(target);
if (!(entityByID instanceof ContraptionEntity))
return;
ContraptionEntity contraptionEntity = (ContraptionEntity) entityByID;
if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand))
sender.swingHand(interactionHand, true);
});
context.get()
.setPacketHandled(true);
}
}

View file

@ -0,0 +1,58 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent.Context;
public class ContraptionSeatMappingPacket extends SimplePacketBase {
private Map<UUID, Integer> mapping;
private int entityID;
public ContraptionSeatMappingPacket(int entityID, Map<UUID, Integer> mapping) {
this.entityID = entityID;
this.mapping = mapping;
}
public ContraptionSeatMappingPacket(PacketBuffer buffer) {
entityID = buffer.readInt();
mapping = new HashMap<>();
short size = buffer.readShort();
for (int i = 0; i < size; i++)
mapping.put(buffer.readUniqueId(), (int) buffer.readShort());
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeInt(entityID);
buffer.writeShort(mapping.size());
mapping.forEach((k, v) -> {
buffer.writeUniqueId(k);
buffer.writeShort(v);
});
}
@Override
public void handle(Supplier<Context> context) {
context.get()
.enqueueWork(() -> {
Entity entityByID = Minecraft.getInstance().world
.getEntityByID(entityID);
if (!(entityByID instanceof ContraptionEntity))
return;
ContraptionEntity contraptionEntity = (ContraptionEntity) entityByID;
contraptionEntity.contraption.seatMapping = mapping;
});
context.get()
.setPacketHandled(true);
}
}

View file

@ -47,10 +47,6 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
if (running && Contraption.isFrozen()) if (running && Contraption.isFrozen())
disassemble(); disassemble();
if (hourHand != null)
hourHand.collisionTick();
if (minuteHand != null)
minuteHand.collisionTick();
if (!world.isRemote && assembleNextTick) { if (!world.isRemote && assembleNextTick) {
assembleNextTick = false; assembleNextTick = false;

View file

@ -208,8 +208,6 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
if (world.isRemote) if (world.isRemote)
clientAngleDiff /= 2; clientAngleDiff /= 2;
if (movedContraption != null)
movedContraption.collisionTick();
if (running && Contraption.isFrozen()) if (running && Contraption.isFrozen())
disassemble(); disassemble();

View file

@ -20,7 +20,6 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.gen.feature.template.Template.BlockInfo;
@ -91,13 +90,13 @@ public class MountedContraption extends Contraption {
} }
@Override @Override
public void removeBlocksFromWorld(IWorld world, BlockPos offset) { protected boolean customBlockPlacement(IWorld world, BlockPos pos, BlockState state) {
super.removeBlocksFromWorld(world, offset, (pos, state) -> pos.equals(anchor)); return AllBlocks.MINECART_ANCHOR.has(state);
} }
@Override @Override
public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) { protected boolean customBlockRemoval(IWorld world, BlockPos pos, BlockState state) {
super.addBlocksToWorld(world, offset, rotation, (pos, state) -> AllBlocks.MINECART_ANCHOR.has(state)); return pos.equals(anchor);
} }
} }

View file

@ -53,7 +53,6 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
super.tick(); super.tick();
if (movedContraption != null) { if (movedContraption != null) {
movedContraption.collisionTick();
if (!movedContraption.isAlive()) if (!movedContraption.isAlive())
movedContraption = null; movedContraption = null;
} }

View file

@ -16,7 +16,6 @@ import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.contraptions.components.structureMovement.AllContraptionTypes; import com.simibubi.create.content.contraptions.components.structureMovement.AllContraptionTypes;
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits; import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
@ -32,7 +31,6 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraft.world.gen.feature.template.Template.BlockInfo;
@ -174,44 +172,36 @@ public class PistonContraption extends Contraption {
} }
@Override @Override
public void addGlue(SuperGlueEntity entity) { public BlockPos toLocalPos(BlockPos globalPos) {
BlockPos pos = entity.getHangingPosition(); return globalPos.subtract(anchor)
Direction direction = entity.getFacingDirection();
BlockPos localPos = pos.subtract(anchor)
.offset(orientation, -initialExtensionProgress); .offset(orientation, -initialExtensionProgress);
this.superglue.add(Pair.of(localPos, direction));
glueToRemove.add(entity);
} }
@Override @Override
public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) { protected boolean customBlockPlacement(IWorld world, BlockPos pos, BlockState state) {
super.addBlocksToWorld(world, offset, rotation, (pos, state) -> { BlockPos pistonPos = anchor.offset(orientation, -1);
BlockPos pistonPos = anchor.offset(orientation, -1); BlockState pistonState = world.getBlockState(pistonPos);
BlockState pistonState = world.getBlockState(pistonPos); TileEntity te = world.getTileEntity(pistonPos);
TileEntity te = world.getTileEntity(pistonPos); if (pos.equals(pistonPos)) {
if (pos.equals(pistonPos)) { if (te == null || te.isRemoved())
if (te == null || te.isRemoved())
return true;
if (!isExtensionPole(state) && isPiston(pistonState))
world.setBlockState(pistonPos, pistonState.with(MechanicalPistonBlock.STATE, PistonState.RETRACTED),
3 | 16);
return true; return true;
} if (!isExtensionPole(state) && isPiston(pistonState))
return false; world.setBlockState(pistonPos, pistonState.with(MechanicalPistonBlock.STATE, PistonState.RETRACTED),
}); 3 | 16);
return true;
}
return false;
} }
@Override @Override
public void removeBlocksFromWorld(IWorld world, BlockPos offset) { protected boolean customBlockRemoval(IWorld world, BlockPos pos, BlockState state) {
super.removeBlocksFromWorld(world, offset, (pos, state) -> { BlockPos pistonPos = anchor.offset(orientation, -1);
BlockPos pistonPos = anchor.offset(orientation, -1); BlockState blockState = world.getBlockState(pos);
BlockState blockState = world.getBlockState(pos); if (pos.equals(pistonPos) && isPiston(blockState)) {
if (pos.equals(pistonPos) && isPiston(blockState)) { world.setBlockState(pos, blockState.with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66 | 16);
world.setBlockState(pos, blockState.with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66 | 16); return true;
return true; }
} return false;
return false;
});
} }
@Override @Override

View file

@ -6,7 +6,6 @@ import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.collision.ContinuousOBBCollider.ContinuousSeparationManifold; import com.simibubi.create.foundation.collision.ContinuousOBBCollider.ContinuousSeparationManifold;
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Debug;
import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.MatrixStacker;
import com.simibubi.create.foundation.utility.outliner.AABBOutline; import com.simibubi.create.foundation.utility.outliner.AABBOutline;
@ -31,7 +30,6 @@ public class CollisionDebugger {
angle += delta; angle += delta;
angle = (int) angle; angle = (int) angle;
OBB.setRotation(new Matrix3d().asZRotation(AngleHelper.rad(angle))); OBB.setRotation(new Matrix3d().asZRotation(AngleHelper.rad(angle)));
Debug.debugMessage("Angle: " + angle);
} }
public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) { public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) {

View file

@ -6,6 +6,8 @@ import java.util.function.Supplier;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.CancelPlayerFallPacket; import com.simibubi.create.content.contraptions.components.structureMovement.CancelPlayerFallPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionInteractionPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionSeatMappingPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket; import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket;
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket; import com.simibubi.create.content.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket;
@ -45,6 +47,7 @@ public enum AllPackets {
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new), CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new),
CANCEL_FALL(CancelPlayerFallPacket.class, CancelPlayerFallPacket::new), CANCEL_FALL(CancelPlayerFallPacket.class, CancelPlayerFallPacket::new),
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new), EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new),
CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new),
PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new), PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new),
// Server to Client // Server to Client
@ -54,6 +57,7 @@ public enum AllPackets {
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new), CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new),
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new), CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new),
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new), GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new),
CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new),
; ;

View file

@ -13,6 +13,10 @@ import net.minecraft.util.math.Vec3i;
public class VecHelper { public class VecHelper {
public static Vec3d rotate(Vec3d vec, Vec3d rotationVec) {
return rotate(vec, rotationVec.x, rotationVec.y, rotationVec.z);
}
public static Vec3d rotate(Vec3d vec, double xRot, double yRot, double zRot) { 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); return rotate(rotate(rotate(vec, xRot, Axis.X), yRot, Axis.Y), zRot, Axis.Z);
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 B

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 B

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 B

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 B

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 407 B

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 B

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 407 B

After

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 B

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 404 B