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 =
register("super_glue", SuperGlueEntity::new, EntityClassification.MISC, 10, Integer.MAX_VALUE, false, SuperGlueEntity::build);
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,
EntityClassification group, int range, int updateFrequency, boolean sendVelocity,

View file

@ -1,17 +1,25 @@
package com.simibubi.create.content.contraptions.components.actors;
import java.util.List;
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.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MobEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext;
@ -19,8 +27,9 @@ import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
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;
public SeatBlock(Properties p_i48440_1_, boolean inCreativeTab) {
@ -41,8 +50,21 @@ public class SeatBlock extends Block {
}
@Override
public void onLanded(IBlockReader p_176216_1_, Entity p_176216_2_) {
Blocks.PINK_BED.onLanded(p_176216_1_, p_176216_2_);
public void onLanded(IBlockReader reader, Entity entity) {
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
@ -52,17 +74,46 @@ public class SeatBlock extends Block {
}
@Override
public ActionResultType onUse(BlockState p_225533_1_, World world, BlockPos pos, PlayerEntity player, Hand p_225533_5_, BlockRayTraceResult p_225533_6_) {
if (SeatEntity.TAKEN.containsKey(pos))
return ActionResultType.FAIL;
public ActionResultType onUse(BlockState p_225533_1_, World world, BlockPos pos, PlayerEntity player,
Hand p_225533_5_, BlockRayTraceResult p_225533_6_) {
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)
return ActionResultType.SUCCESS;
SeatEntity seat = new SeatEntity(world, pos);
world.addEntity(seat);
player.startRiding(seat);
sitDown(world, pos, player);
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;
import com.simibubi.create.AllEntityTypes;
import net.minecraft.client.renderer.culling.ClippingHelperImpl;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager;
@ -8,18 +9,16 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.IPacket;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
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.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.network.NetworkHooks;
import java.util.HashMap;
import java.util.Map;
public class SeatEntity extends Entity {
public static final Map<BlockPos, SeatEntity> TAKEN = new HashMap<>();
public class SeatEntity extends Entity implements IEntityAdditionalSpawnData {
public SeatEntity(EntityType<?> p_i48580_1_, World 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) {
this(AllEntityTypes.SEAT.get(), world);
this.setPos(pos.getX() + 0.5, pos.getY() + 0.30, pos.getZ() + 0.5);
noClip = true;
TAKEN.put(pos, this);
}
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
@SuppressWarnings("unchecked")
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
public void tick() {
if (world.isRemote)
return;
BlockPos blockPos = new BlockPos(getX(), getY(), getZ());
if (isBeingRidden() && world.getBlockState(blockPos).getBlock() instanceof SeatBlock)
boolean blockPresent = world.getBlockState(getPosition())
.getBlock() instanceof SeatBlock;
if (isBeingRidden() && blockPresent)
return;
TAKEN.remove(blockPos);
this.remove();
}
@ -61,7 +71,7 @@ public class SeatEntity extends Entity {
protected void removePassenger(Entity entity) {
super.removePassenger(entity);
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
@ -85,7 +95,8 @@ public class SeatEntity extends Entity {
}
@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;
}
@ -94,4 +105,10 @@ public class SeatEntity extends Entity {
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

@ -1,7 +1,29 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.actors.SeatBlock;
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
import com.simibubi.create.content.contraptions.components.saw.SawBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisTileEntity;
@ -22,9 +44,19 @@ import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
import net.minecraft.block.*;
import net.minecraft.block.AbstractButtonBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.ChestBlock;
import net.minecraft.block.DoorBlock;
import net.minecraft.block.IWaterLoggable;
import net.minecraft.block.PressurePlateBlock;
import net.minecraft.block.SlimeBlock;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.entity.Entity;
import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState;
import net.minecraft.nbt.CompoundNBT;
@ -45,19 +77,9 @@ import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.common.util.Constants.BlockFlags;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead;
public abstract class Contraption {
@ -71,6 +93,10 @@ public abstract class Contraption {
public AxisAlignedBB bounds;
public boolean stalled;
protected List<BlockPos> seats;
protected Map<UUID, Integer> seatMapping;
protected Map<BlockPos, Entity> initialPassengers;
protected Set<BlockPos> cachedColliders;
protected Direction cachedColliderDirection;
protected BlockPos anchor;
@ -81,6 +107,9 @@ public abstract class Contraption {
blocks = new HashMap<>();
storage = new HashMap<>();
actors = new ArrayList<>();
seats = new ArrayList<>();
seatMapping = new HashMap<>();
initialPassengers = new HashMap<>();
superglue = new HashSet<>();
renderOrder = new ArrayList<>();
customRenderTEs = new ArrayList<>();
@ -144,6 +173,7 @@ public abstract class Contraption {
}
public boolean searchMovedStructure(World world, BlockPos pos, @Nullable Direction forcedDirection) {
initialPassengers.clear();
List<BlockPos> frontier = new ArrayList<>();
Set<BlockPos> visited = new HashSet<>();
anchor = pos;
@ -172,6 +202,20 @@ public abstract class Contraption {
inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
}
public void mountPassengers(ContraptionEntity contraptionEntity) {
if (contraptionEntity.world.isRemote)
return;
for (BlockPos seatPos : seats) {
Entity passenger = initialPassengers.get(seatPos);
if (passenger == null)
continue;
int seatIndex = seats.indexOf(seatPos);
if (seatIndex == -1)
continue;
contraptionEntity.addSittingPassenger(passenger, seatIndex);
}
}
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection,
List<BlockPos> frontier) {
return true;
@ -205,6 +249,19 @@ public abstract class Contraption {
frontier.add(prevPos);
}
// Seats transfer their passenger to the contraption
if (state.getBlock() instanceof SeatBlock) {
BlockPos local = toLocalPos(pos);
seats.add(local);
List<SeatEntity> seatsEntities = world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos));
if (!seatsEntities.isEmpty()) {
SeatEntity seat = seatsEntities.get(0);
List<Entity> passengers = seat.getPassengers();
if (!passengers.isEmpty())
initialPassengers.put(local, passengers.get(0));
}
}
// Pulleys drag their rope and their attached structure
if (state.getBlock() instanceof PulleyBlock) {
int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get();
@ -356,11 +413,14 @@ public abstract class Contraption {
public void addGlue(SuperGlueEntity entity) {
BlockPos pos = entity.getHangingPosition();
Direction direction = entity.getFacingDirection();
BlockPos localPos = pos.subtract(anchor);
this.superglue.add(Pair.of(localPos, direction));
this.superglue.add(Pair.of(toLocalPos(pos), direction));
glueToRemove.add(entity);
}
public BlockPos toLocalPos(BlockPos globalPos) {
return globalPos.subtract(anchor);
}
public void add(BlockPos pos, Pair<BlockInfo, TileEntity> pair) {
BlockInfo captured = pair.getKey();
BlockPos localPos = pos.subtract(anchor);
@ -374,7 +434,7 @@ public abstract class Contraption {
if (te != null && MountedStorage.canUseAsStorage(te))
storage.put(localPos, new MountedStorage(te));
if (captured.state.getBlock() instanceof IPortableBlock)
getActors().add(MutablePair.of(blockInfo, null));
actors.add(MutablePair.of(blockInfo, null));
}
public void readNBT(World world, CompoundNBT nbt) {
@ -456,6 +516,12 @@ public abstract class Contraption {
if (nbt.contains("BoundsFront"))
bounds = NBTHelper.readAABB(nbt.getList("BoundsFront", 5));
seats.clear();
NBTHelper.iterateCompoundList(nbt.getList("Seats", NBT.TAG_COMPOUND), c -> seats.add(NBTUtil.readBlockPos(c)));
seatMapping.clear();
NBTHelper.iterateCompoundList(nbt.getList("Passengers", NBT.TAG_COMPOUND),
c -> seatMapping.put(NBTUtil.readUniqueId(c.getCompound("Id")), c.getInt("Seat")));
stalled = nbt.getBoolean("Stalled");
anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor"));
}
@ -502,6 +568,14 @@ public abstract class Contraption {
storageNBT.add(c);
}
nbt.put("Seats", NBTHelper.writeCompoundList(seats, NBTUtil::writeBlockPos));
nbt.put("Passengers", NBTHelper.writeCompoundList(seatMapping.entrySet(), e -> {
CompoundNBT tag = new CompoundNBT();
tag.put("Id", NBTUtil.writeUniqueId(e.getKey()));
tag.putInt("Seat", e.getValue());
return tag;
}));
nbt.put("Blocks", blocksNBT);
nbt.put("Actors", actorsNBT);
nbt.put("Superglue", superglueNBT);
@ -517,25 +591,29 @@ public abstract class Contraption {
return nbt;
}
public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
removeBlocksFromWorld(world, offset, (pos, state) -> false);
protected boolean customBlockPlacement(IWorld world, BlockPos pos, BlockState state) {
return false;
}
public void removeBlocksFromWorld(IWorld world, BlockPos offset, BiPredicate<BlockPos, BlockState> customRemoval) {
protected boolean customBlockRemoval(IWorld world, BlockPos pos, BlockState state) {
return false;
}
public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
storage.values()
.forEach(MountedStorage::empty);
glueToRemove.forEach(SuperGlueEntity::remove);
for (boolean brittles : Iterate.trueAndFalse) {
for (Iterator<BlockInfo> iterator = blocks.values()
.iterator(); iterator.hasNext(); ) {
.iterator(); iterator.hasNext();) {
BlockInfo block = iterator.next();
if (brittles != BlockMovementTraits.isBrittle(block.state))
continue;
BlockPos add = block.pos.add(anchor)
.add(offset);
if (customRemoval.test(add, block.state))
if (customBlockRemoval(world, add, block.state))
continue;
BlockState oldState = world.getBlockState(add);
Block blockIn = oldState.getBlock();
@ -546,7 +624,9 @@ public abstract class Contraption {
int flags = 67;
if (blockIn instanceof DoorBlock)
flags = flags | 32 | 16;
if (blockIn instanceof IWaterLoggable && oldState.has(BlockStateProperties.WATERLOGGED) && oldState.get(BlockStateProperties.WATERLOGGED).booleanValue()) {
if (blockIn instanceof IWaterLoggable && oldState.has(BlockStateProperties.WATERLOGGED)
&& oldState.get(BlockStateProperties.WATERLOGGED)
.booleanValue()) {
world.setBlockState(add, Blocks.WATER.getDefaultState(), flags);
continue;
}
@ -555,12 +635,7 @@ public abstract class Contraption {
}
}
public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) {
addBlocksToWorld(world, offset, rotation, (pos, state) -> false);
}
public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation,
BiPredicate<BlockPos, BlockState> customPlacement) {
public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation, List<Entity> seatedEntities) {
stop(world);
StructureTransform transform = new StructureTransform(offset, rotation);
@ -570,10 +645,9 @@ public abstract class Contraption {
continue;
BlockPos targetPos = transform.apply(block.pos);
BlockState state = transform.apply(block.state);
if (customPlacement.test(targetPos, state))
if (customBlockPlacement(world, targetPos, state))
continue;
if (nonBrittles)
@ -597,7 +671,8 @@ public abstract class Contraption {
}
if (state.getBlock() instanceof IWaterLoggable && state.has(BlockStateProperties.WATERLOGGED)) {
IFluidState ifluidstate = world.getFluidState(targetPos);
state = state.with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER));
state = state.with(BlockStateProperties.WATERLOGGED,
Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER));
}
world.destroyBlock(targetPos, true);
@ -642,7 +717,20 @@ public abstract class Contraption {
if (!world.isRemote)
world.addEntity(entity);
}
}
for (Entity seatedEntity : seatedEntities) {
if (seatMapping.isEmpty())
continue;
Integer seatIndex = seatMapping.get(seatedEntity.getUniqueID());
BlockPos seatPos = seats.get(seatIndex);
seatPos = transform.apply(seatPos);
if (!(world.getBlockState(seatPos)
.getBlock() instanceof SeatBlock))
continue;
if (SeatBlock.isSeatOccupied(world, seatPos))
continue;
SeatBlock.sitDown(world, seatPos, seatedEntity);
}
}
@ -707,6 +795,15 @@ public abstract class Contraption {
bounds = new AxisAlignedBB(min, max);
}
public BlockPos getSeat(UUID entityId) {
if (!seatMapping.containsKey(entityId))
return null;
int seatIndex = seatMapping.get(entityId);
if (seatIndex >= seats.size())
return null;
return seats.get(seatIndex);
}
protected abstract AllContraptionTypes getType();
}

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.OrientedBB;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
@ -32,9 +33,11 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction;
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.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.event.TickEvent.ClientTickEvent;
import net.minecraftforge.event.TickEvent.Phase;
import net.minecraftforge.event.TickEvent.WorldTickEvent;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@ -66,7 +71,7 @@ public class ContraptionCollider {
new DamageSource("create.contraption_suffocate").setDamageBypassesArmor();
public static boolean wasClientPlayerGrounded;
public static Cache<World, List<WeakReference<ContraptionEntity>>> activeContraptions = CacheBuilder.newBuilder()
.expireAfterAccess(40, SECONDS)
.expireAfterAccess(400, SECONDS)
.build();
@SubscribeEvent
@ -102,6 +107,22 @@ public class ContraptionCollider {
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) {
List<WeakReference<ContraptionEntity>> list = activeContraptions.getIfPresent(world);
if (list == null)
@ -131,9 +152,9 @@ public class ContraptionCollider {
return;
Vec3d centerOfBlock = VecHelper.getCenterOf(BlockPos.ZERO);
double conRotX = contraptionRotation.z;
double conRotX = contraptionRotation.x;
double conRotY = contraptionRotation.y;
double conRotZ = contraptionRotation.x;
double conRotZ = contraptionRotation.z;
Vec3d conMotion = contraptionPosition.subtract(contraptionEntity.getPrevPositionVec());
Vec3d conAngularMotion = contraptionRotation.subtract(contraptionEntity.getPrevRotationVec());
Vec3d contraptionCentreOffset = contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0);
@ -180,6 +201,7 @@ public class ContraptionCollider {
// Prepare entity bounds
OrientedBB obb = new OrientedBB(localBB);
obb.setRotation(rotation);
motion = motion.subtract(conMotion);
motion = rotation.transform(motion);
// Vec3d visualizerOrigin = new Vec3d(10, 64, 0);
@ -198,40 +220,47 @@ public class ContraptionCollider {
.forEach(shape -> shape.toBoundingBoxList()
.forEach(bbs::add));
boolean doHorizontalPass = conRotX == 0 && conRotZ == 0;
for (boolean horizontalPass : Iterate.trueAndFalse) {
for (AxisAlignedBB bb : bbs) {
Vec3d currentResponse = collisionResponse.getValue();
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)
continue;
if (surfaceCollision.isFalse())
if ((!horizontalPass || !doHorizontalPass) && surfaceCollision.isFalse())
surfaceCollision.setValue(intersect.isSurfaceCollision());
double timeOfImpact = intersect.getTimeOfImpact();
if (timeOfImpact > 0 && timeOfImpact < 1) {
futureCollision.setTrue();
// Vec3d prev = allowedMotion.getValue();
allowedMotion.setValue(intersect.getAllowedMotion(allowedMotion.getValue()));
// Debug.debugChat("Allowed Motion FROM " + prev.toString());
// Debug.debugChat("Allowed Motion TO " + allowedMotion.getValue()
// .toString());
// params.colored(0x4499ff);
continue;
}
Vec3d separation = intersect.asSeparationVec(entity.stepHeight);
if (separation != null && !separation.equals(Vec3d.ZERO)) {
if (separation != null && !separation.equals(Vec3d.ZERO))
collisionResponse.setValue(currentResponse.add(separation));
// Debug.debugChat("Collision " + currentResponse.add(separation)
// .toString());
// params.colored(0xff9944);
}
}
// Debug.debugChat("----");
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;
}
// Resolve collision
Vec3d entityMotion = entity.getMotion();
@ -240,7 +269,8 @@ public class ContraptionCollider {
boolean hardCollision = !totalResponse.equals(Vec3d.ZERO);
rotation.transpose();
motionResponse = rotation.transform(motionResponse);
motionResponse = rotation.transform(motionResponse)
.add(conMotion);
totalResponse = rotation.transform(totalResponse);
rotation.transpose();
@ -262,7 +292,7 @@ public class ContraptionCollider {
Vec3d contactPoint = entityPosition.subtract(contraptionCentreOffset)
.subtract(contraptionPosition);
contactPoint =
VecHelper.rotate(contactPoint, conAngularMotion.z, conAngularMotion.y, conAngularMotion.x);
VecHelper.rotate(contactPoint, conAngularMotion.x, conAngularMotion.y, conAngularMotion.z);
contactPoint = contactPoint.add(contraptionPosition)
.add(contraptionCentreOffset)
.add(conMotion);

View file

@ -5,12 +5,15 @@ import static com.simibubi.create.foundation.utility.AngleHelper.getShortestAngl
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.stream.Stream;
import org.apache.commons.lang3.tuple.MutablePair;
import com.google.common.collect.ImmutableSet;
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.glue.SuperGlueEntity;
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.util.DamageSource;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.ReuseableStream;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
@ -70,7 +74,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
protected BlockPos controllerPos;
protected Vec3d motionBeforeStall;
protected boolean stationary;
protected boolean initialized;
final List<Entity> collidingEntities = new ArrayList<>();
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) {
ContraptionEntity entity = new ContraptionEntity(AllEntityTypes.CONTRAPTION.get(), world);
entity.contraption = contraption;
entity.contraptionCreated(contraption);
entity.initialAngle = initialAngle;
entity.forceYaw(initialAngle);
if (contraption != null)
contraption.gatherStoredItems();
return entity;
}
@ -116,12 +118,25 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
public static ContraptionEntity createStationary(World world, Contraption contraption) {
ContraptionEntity entity = new ContraptionEntity(AllEntityTypes.STATIONARY_CONTRAPTION.get(), world);
entity.contraption = contraption;
if (contraption != null)
contraption.gatherStoredItems();
entity.contraptionCreated(contraption);
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) {
this.controllerPos = controller.getPos();
return this;
@ -142,6 +157,110 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
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
public void tick() {
if (contraption == null) {
@ -149,6 +268,9 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
return;
}
if (!initialized)
contraptionInitialize();
checkController();
Entity mountedEntity = getRidingEntity();
@ -173,10 +295,6 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
super.tick();
}
public void collisionTick() {
// ContraptionCollider.collideEntities(this);
}
public void tickAsPassenger(Entity e) {
boolean rotationLock = false;
boolean pauseWhileRotating = false;
@ -266,10 +384,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
}
public void tickActors(Vec3d movementVector) {
float anglePitch = getPitch(1);
float angleYaw = getYaw(1);
float angleRoll = getRoll(1);
Vec3d rotationVec = new Vec3d(angleRoll, angleYaw, anglePitch);
Vec3d rotationVec = getRotationVec();
Vec3d reversedRotationVec = rotationVec.scale(-1);
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
boolean stalledPreviously = contraption.stalled;
@ -283,7 +399,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
Vec3d actorPosition = new Vec3d(blockInfo.pos);
actorPosition = actorPosition.add(actor.getActiveAreaOffset(context));
actorPosition = VecHelper.rotate(actorPosition, angleRoll, angleYaw, anglePitch);
actorPosition = VecHelper.rotate(actorPosition, rotationVec);
actorPosition = actorPosition.add(rotationOffset)
.add(getAnchorVec());
@ -295,7 +411,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (previousPosition != null) {
context.motion = actorPosition.subtract(previousPosition);
Vec3d relativeMotion = context.motion;
relativeMotion = VecHelper.rotate(relativeMotion, -angleRoll, -angleYaw, -anglePitch);
relativeMotion = VecHelper.rotate(relativeMotion, reversedRotationVec);
context.relativeMotion = relativeMotion;
newPosVisited = !new BlockPos(previousPosition).equals(gridPosition)
|| context.relativeMotion.length() > 0 && context.firstMovement;
@ -429,6 +545,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
@Override
protected void readAdditional(CompoundNBT compound) {
initialized = compound.getBoolean("Initialized");
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
initialAngle = compound.getFloat("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.putBoolean("Stalled", isStalled());
compound.putBoolean("Initialized", initialized);
}
@Override
@ -499,15 +617,15 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
}
public void disassemble() {
if (!isAlive()) {
if (!isAlive())
return;
}
if (getContraption() != null) {
remove();
BlockPos offset = new BlockPos(getAnchorVec().add(.5, .5, .5));
Vec3d rotation = new Vec3d(getRoll(1), getYaw(1), getPitch(1));
getContraption().addBlocksToWorld(world, offset, rotation);
preventMovedEntitiesFromGettingStuck();
Vec3d rotation = getRotationVec();
setBoundingBox(new AxisAlignedBB(0, 300, 0, 0, 300, 0));
contraption.addBlocksToWorld(world, offset, rotation, getPassengers());
// preventMovedEntitiesFromGettingStuck();
}
}
@ -633,11 +751,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
}
public Vec3d getRotationVec() {
return new Vec3d(getPitch(1), getYaw(1), getRoll(1));
return new Vec3d(getRoll(1), getYaw(1), getPitch(1));
}
public Vec3d getPrevRotationVec() {
return new Vec3d(getPitch(0), getYaw(0), getRoll(0));
return new Vec3d(getRoll(0), getYaw(0), getPitch(0));
}
public Vec3d getPrevPositionVec() {
@ -653,8 +771,12 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
return false;
if (e instanceof SuperGlueEntity)
return false;
if (e instanceof SeatEntity)
return false;
if (e instanceof IProjectile)
return false;
if (e.getRidingEntity() != null)
return false;
Entity riding = this.getRidingEntity();
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())
disassemble();
if (hourHand != null)
hourHand.collisionTick();
if (minuteHand != null)
minuteHand.collisionTick();
if (!world.isRemote && assembleNextTick) {
assembleNextTick = false;

View file

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

View file

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

View file

@ -53,7 +53,6 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
super.tick();
if (movedContraption != null) {
movedContraption.collisionTick();
if (!movedContraption.isAlive())
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.BlockMovementTraits;
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.foundation.config.AllConfigs;
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.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;
@ -174,18 +172,13 @@ public class PistonContraption extends Contraption {
}
@Override
public void addGlue(SuperGlueEntity entity) {
BlockPos pos = entity.getHangingPosition();
Direction direction = entity.getFacingDirection();
BlockPos localPos = pos.subtract(anchor)
public BlockPos toLocalPos(BlockPos globalPos) {
return globalPos.subtract(anchor)
.offset(orientation, -initialExtensionProgress);
this.superglue.add(Pair.of(localPos, direction));
glueToRemove.add(entity);
}
@Override
public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) {
super.addBlocksToWorld(world, offset, rotation, (pos, state) -> {
protected boolean customBlockPlacement(IWorld world, BlockPos pos, BlockState state) {
BlockPos pistonPos = anchor.offset(orientation, -1);
BlockState pistonState = world.getBlockState(pistonPos);
TileEntity te = world.getTileEntity(pistonPos);
@ -198,12 +191,10 @@ public class PistonContraption extends Contraption {
return true;
}
return false;
});
}
@Override
public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
super.removeBlocksFromWorld(world, offset, (pos, state) -> {
protected boolean customBlockRemoval(IWorld world, BlockPos pos, BlockState state) {
BlockPos pistonPos = anchor.offset(orientation, -1);
BlockState blockState = world.getBlockState(pos);
if (pos.equals(pistonPos) && isPiston(blockState)) {
@ -211,7 +202,6 @@ public class PistonContraption extends Contraption {
return true;
}
return false;
});
}
@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.renderState.SuperRenderTypeBuffer;
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.outliner.AABBOutline;
@ -31,7 +30,6 @@ public class CollisionDebugger {
angle += delta;
angle = (int) angle;
OBB.setRotation(new Matrix3d().asZRotation(AngleHelper.rad(angle)));
Debug.debugMessage("Angle: " + angle);
}
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.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.glue.GlueEffectPacket;
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket;
@ -45,6 +47,7 @@ public enum AllPackets {
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new),
CANCEL_FALL(CancelPlayerFallPacket.class, CancelPlayerFallPacket::new),
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new),
CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new),
PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new),
// Server to Client
@ -54,6 +57,7 @@ public enum AllPackets {
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new),
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::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 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) {
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