mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-16 00:43:41 +01:00
Refactor Attractor
- More cleaning up and major refactoring in Contraption entity implementation (needs testing) - Minecarts can no longer be mounted on seats - Mechanical bearings now "stabilize" rotation of a contraption with an attached sub-contraption
This commit is contained in:
parent
78ffba254e
commit
e5c4b31458
54 changed files with 2553 additions and 1843 deletions
|
@ -46,6 +46,7 @@ import com.simibubi.create.content.contraptions.components.motor.CreativeMotorGe
|
||||||
import com.simibubi.create.content.contraptions.components.press.MechanicalPressBlock;
|
import com.simibubi.create.content.contraptions.components.press.MechanicalPressBlock;
|
||||||
import com.simibubi.create.content.contraptions.components.saw.SawBlock;
|
import com.simibubi.create.content.contraptions.components.saw.SawBlock;
|
||||||
import com.simibubi.create.content.contraptions.components.saw.SawGenerator;
|
import com.simibubi.create.content.contraptions.components.saw.SawGenerator;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedBearingMovementBehaviour;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingBlock;
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingBlock;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock;
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlock;
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlock;
|
||||||
|
@ -668,6 +669,7 @@ public class AllBlocks {
|
||||||
REGISTRATE.block("mechanical_bearing", MechanicalBearingBlock::new)
|
REGISTRATE.block("mechanical_bearing", MechanicalBearingBlock::new)
|
||||||
.transform(BuilderTransformers.bearing("mechanical", "gearbox", false))
|
.transform(BuilderTransformers.bearing("mechanical", "gearbox", false))
|
||||||
.transform(StressConfigDefaults.setImpact(4.0))
|
.transform(StressConfigDefaults.setImpact(4.0))
|
||||||
|
.onRegister(addMovementBehaviour(new StabilizedBearingMovementBehaviour()))
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntry<ClockworkBearingBlock> CLOCKWORK_BEARING =
|
public static final BlockEntry<ClockworkBearingBlock> CLOCKWORK_BEARING =
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package com.simibubi.create;
|
package com.simibubi.create;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
|
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntityRenderer;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntityRenderer;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntityRenderer;
|
||||||
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.glue.SuperGlueRenderer;
|
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueRenderer;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
@ -19,12 +22,14 @@ import net.minecraftforge.fml.client.registry.RenderingRegistry;
|
||||||
|
|
||||||
public class AllEntityTypes {
|
public class AllEntityTypes {
|
||||||
|
|
||||||
public static final RegistryEntry<EntityType<ContraptionEntity>> CONTRAPTION =
|
public static final RegistryEntry<EntityType<OrientedContraptionEntity>> ORIENTED_CONTRAPTION =
|
||||||
register("contraption", ContraptionEntity::new, EntityClassification.MISC, 5, 3, true, ContraptionEntity::build);
|
register("contraption", OrientedContraptionEntity::new, EntityClassification.MISC, 5, 3, true,
|
||||||
public static final RegistryEntry<EntityType<ContraptionEntity>> STATIONARY_CONTRAPTION =
|
AbstractContraptionEntity::build);
|
||||||
register("stationary_contraption", ContraptionEntity::new, EntityClassification.MISC, 20, 40, false, ContraptionEntity::build);
|
public static final RegistryEntry<EntityType<ControlledContraptionEntity>> CONTROLLED_CONTRAPTION =
|
||||||
public static final RegistryEntry<EntityType<SuperGlueEntity>> SUPER_GLUE =
|
register("stationary_contraption", ControlledContraptionEntity::new, EntityClassification.MISC, 20, 40, false,
|
||||||
register("super_glue", SuperGlueEntity::new, EntityClassification.MISC, 10, Integer.MAX_VALUE, false, SuperGlueEntity::build);
|
AbstractContraptionEntity::build);
|
||||||
|
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 =
|
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, 0, Integer.MAX_VALUE, false, SeatEntity::build);
|
||||||
|
|
||||||
|
@ -32,9 +37,9 @@ public class AllEntityTypes {
|
||||||
EntityClassification group, int range, int updateFrequency, boolean sendVelocity,
|
EntityClassification group, int range, int updateFrequency, boolean sendVelocity,
|
||||||
NonNullConsumer<EntityType.Builder<T>> propertyBuilder) {
|
NonNullConsumer<EntityType.Builder<T>> propertyBuilder) {
|
||||||
String id = Lang.asId(name);
|
String id = Lang.asId(name);
|
||||||
return Create.registrate().entity(id, factory, group)
|
return Create.registrate()
|
||||||
.properties(b -> b
|
.entity(id, factory, group)
|
||||||
.setTrackingRange(range)
|
.properties(b -> b.setTrackingRange(range)
|
||||||
.setUpdateInterval(updateFrequency)
|
.setUpdateInterval(updateFrequency)
|
||||||
.setShouldReceiveVelocityUpdates(sendVelocity))
|
.setShouldReceiveVelocityUpdates(sendVelocity))
|
||||||
.properties(propertyBuilder)
|
.properties(propertyBuilder)
|
||||||
|
@ -45,8 +50,10 @@ public class AllEntityTypes {
|
||||||
|
|
||||||
@OnlyIn(value = Dist.CLIENT)
|
@OnlyIn(value = Dist.CLIENT)
|
||||||
public static void registerRenderers() {
|
public static void registerRenderers() {
|
||||||
RenderingRegistry.registerEntityRenderingHandler(STATIONARY_CONTRAPTION.get(), ContraptionEntityRenderer::new);
|
RenderingRegistry.registerEntityRenderingHandler(CONTROLLED_CONTRAPTION.get(),
|
||||||
RenderingRegistry.registerEntityRenderingHandler(CONTRAPTION.get(), ContraptionEntityRenderer::new);
|
ControlledContraptionEntityRenderer::new);
|
||||||
|
RenderingRegistry.registerEntityRenderingHandler(ORIENTED_CONTRAPTION.get(),
|
||||||
|
OrientedContraptionEntityRenderer::new);
|
||||||
RenderingRegistry.registerEntityRenderingHandler(SUPER_GLUE.get(), SuperGlueRenderer::new);
|
RenderingRegistry.registerEntityRenderingHandler(SUPER_GLUE.get(), SuperGlueRenderer::new);
|
||||||
RenderingRegistry.registerEntityRenderingHandler(SEAT.get(), SeatEntity.Render::new);
|
RenderingRegistry.registerEntityRenderingHandler(SEAT.get(), SeatEntity.Render::new);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov
|
||||||
import com.tterrag.registrate.util.nullness.NonNullConsumer;
|
import com.tterrag.registrate.util.nullness.NonNullConsumer;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
@ -29,16 +30,21 @@ public class AllMovementBehaviours {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static MovementBehaviour getMovementBehaviour(ResourceLocation resourceLocation) {
|
public static MovementBehaviour of(ResourceLocation resourceLocation) {
|
||||||
return movementBehaviours.getOrDefault(resourceLocation, null);
|
return movementBehaviours.getOrDefault(resourceLocation, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static MovementBehaviour getMovementBehaviour(Block block) {
|
public static MovementBehaviour of(Block block) {
|
||||||
return getMovementBehaviour(block.getRegistryName());
|
return of(block.getRegistryName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasMovementBehaviour(Block block) {
|
@Nullable
|
||||||
|
public static MovementBehaviour of(BlockState state) {
|
||||||
|
return of(state.getBlock());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains(Block block) {
|
||||||
return movementBehaviours.containsKey(block.getRegistryName());
|
return movementBehaviours.containsKey(block.getRegistryName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.simibubi.create.content.contraptions.components.actors;
|
package com.simibubi.create.content.contraptions.components.actors;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||||
|
@ -52,12 +52,12 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
|
||||||
Entities: for (Entity entity : world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(pos))) {
|
Entities: for (Entity entity : world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(pos))) {
|
||||||
if (entity instanceof ItemEntity)
|
if (entity instanceof ItemEntity)
|
||||||
continue;
|
continue;
|
||||||
if (entity instanceof ContraptionEntity)
|
if (entity instanceof AbstractContraptionEntity)
|
||||||
continue;
|
continue;
|
||||||
if (entity instanceof AbstractMinecartEntity)
|
if (entity instanceof AbstractMinecartEntity)
|
||||||
for (Entity passenger : entity.getRecursivePassengers())
|
for (Entity passenger : entity.getRecursivePassengers())
|
||||||
if (passenger instanceof ContraptionEntity
|
if (passenger instanceof AbstractContraptionEntity
|
||||||
&& ((ContraptionEntity) passenger).getContraption() == context.contraption)
|
&& ((AbstractContraptionEntity) passenger).getContraption() == context.contraption)
|
||||||
continue Entities;
|
continue Entities;
|
||||||
|
|
||||||
if (damageSource != null && !world.isRemote) {
|
if (damageSource != null && !world.isRemote) {
|
||||||
|
|
|
@ -16,7 +16,6 @@ import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.MobEntity;
|
import net.minecraft.entity.MobEntity;
|
||||||
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.DyeColor;
|
import net.minecraft.item.DyeColor;
|
||||||
import net.minecraft.item.ItemGroup;
|
import net.minecraft.item.ItemGroup;
|
||||||
|
@ -132,8 +131,7 @@ public class SeatBlock extends Block {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canBePickedUp(Entity passenger) {
|
public static boolean canBePickedUp(Entity passenger) {
|
||||||
return !(passenger instanceof PlayerEntity)
|
return !(passenger instanceof PlayerEntity) && (passenger instanceof LivingEntity);
|
||||||
&& (passenger instanceof LivingEntity || passenger instanceof AbstractMinecartEntity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sitDown(World world, BlockPos pos, Entity entity) {
|
public static void sitDown(World world, BlockPos pos, Entity entity) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
@ -30,7 +30,8 @@ public class SeatMovementBehaviour extends MovementBehaviour {
|
||||||
@Override
|
@Override
|
||||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||||
super.visitNewPosition(context, pos);
|
super.visitNewPosition(context, pos);
|
||||||
ContraptionEntity contraptionEntity = context.contraption.entity;
|
|
||||||
|
AbstractContraptionEntity contraptionEntity = context.contraption.entity;
|
||||||
if (contraptionEntity == null)
|
if (contraptionEntity == null)
|
||||||
return;
|
return;
|
||||||
int index = context.data.getInt("SeatIndex");
|
int index = context.data.getInt("SeatIndex");
|
||||||
|
|
|
@ -7,7 +7,7 @@ import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode;
|
import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.content.logistics.item.filter.FilterItem;
|
import com.simibubi.create.content.logistics.item.filter.FilterItem;
|
||||||
|
@ -53,8 +53,8 @@ public class DeployerMovementBehaviour extends MovementBehaviour {
|
||||||
.getDirectionVec());
|
.getDirectionVec());
|
||||||
facingVec = context.rotation.apply(facingVec);
|
facingVec = context.rotation.apply(facingVec);
|
||||||
Vec3d vec = context.position.subtract(facingVec.scale(2));
|
Vec3d vec = context.position.subtract(facingVec.scale(2));
|
||||||
player.rotationYaw = ContraptionEntity.yawFromVector(facingVec);
|
player.rotationYaw = AbstractContraptionEntity.yawFromVector(facingVec);
|
||||||
player.rotationPitch = ContraptionEntity.pitchFromVector(facingVec) - 90;
|
player.rotationPitch = AbstractContraptionEntity.pitchFromVector(facingVec) - 90;
|
||||||
|
|
||||||
DeployerHandler.activate(player, vec, pos, facingVec, mode);
|
DeployerHandler.activate(player, vec, pos, facingVec, mode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,592 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.MutablePair;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllMovementBehaviours;
|
||||||
|
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket;
|
||||||
|
import com.simibubi.create.foundation.collision.Matrix3d;
|
||||||
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.block.material.PushReaction;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.IProjectile;
|
||||||
|
import net.minecraft.entity.item.HangingEntity;
|
||||||
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.network.IPacket;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraft.network.datasync.DataParameter;
|
||||||
|
import net.minecraft.network.datasync.DataSerializers;
|
||||||
|
import net.minecraft.network.datasync.EntityDataManager;
|
||||||
|
import net.minecraft.util.DamageSource;
|
||||||
|
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.Vec3d;
|
||||||
|
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.fml.common.registry.IEntityAdditionalSpawnData;
|
||||||
|
import net.minecraftforge.fml.network.NetworkHooks;
|
||||||
|
import net.minecraftforge.fml.network.PacketDistributor;
|
||||||
|
|
||||||
|
public abstract class AbstractContraptionEntity extends Entity implements IEntityAdditionalSpawnData {
|
||||||
|
|
||||||
|
private static final DataParameter<Boolean> STALLED =
|
||||||
|
EntityDataManager.createKey(AbstractContraptionEntity.class, DataSerializers.BOOLEAN);
|
||||||
|
|
||||||
|
public final List<Entity> collidingEntities = new ArrayList<>();
|
||||||
|
|
||||||
|
protected Contraption contraption;
|
||||||
|
protected boolean initialized;
|
||||||
|
private boolean prevPosInvalid;
|
||||||
|
|
||||||
|
public AbstractContraptionEntity(EntityType<?> entityTypeIn, World worldIn) {
|
||||||
|
super(entityTypeIn, worldIn);
|
||||||
|
prevPosInvalid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setContraption(Contraption contraption) {
|
||||||
|
this.contraption = contraption;
|
||||||
|
if (contraption == null)
|
||||||
|
return;
|
||||||
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
contraption.onEntityCreated(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void contraptionInitialize() {
|
||||||
|
contraption.onEntityInitialize(world, this);
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean collisionEnabled() {
|
||||||
|
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.getSeatMapping()
|
||||||
|
.put(passenger.getUniqueID(), seatIndex);
|
||||||
|
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||||
|
new ContraptionSeatMappingPacket(getEntityId(), contraption.getSeatMapping()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
super.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removePassenger(Entity passenger) {
|
||||||
|
Vec3d transformedVector = getPassengerPosition(passenger, 1);
|
||||||
|
super.removePassenger(passenger);
|
||||||
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
if (transformedVector != null)
|
||||||
|
passenger.getPersistentData()
|
||||||
|
.put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector));
|
||||||
|
contraption.getSeatMapping()
|
||||||
|
.remove(passenger.getUniqueID());
|
||||||
|
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||||
|
new ContraptionSeatMappingPacket(getEntityId(), contraption.getSeatMapping()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updatePassengerPosition(Entity passenger, IMoveCallback callback) {
|
||||||
|
if (!isPassenger(passenger))
|
||||||
|
return;
|
||||||
|
Vec3d transformedVector = getPassengerPosition(passenger, 1);
|
||||||
|
if (transformedVector == null)
|
||||||
|
return;
|
||||||
|
callback.accept(passenger, transformedVector.x, transformedVector.y, transformedVector.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Vec3d getPassengerPosition(Entity passenger, float partialTicks) {
|
||||||
|
UUID id = passenger.getUniqueID();
|
||||||
|
if (passenger instanceof OrientedContraptionEntity) {
|
||||||
|
BlockPos localPos = contraption.getBearingPosOf(id);
|
||||||
|
if (localPos != null)
|
||||||
|
return toGlobalVector(VecHelper.getCenterOf(localPos), partialTicks)
|
||||||
|
.add(VecHelper.getCenterOf(BlockPos.ZERO))
|
||||||
|
.subtract(.5f, 1, .5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
AxisAlignedBB bb = passenger.getBoundingBox();
|
||||||
|
double ySize = bb.getYSize();
|
||||||
|
BlockPos seat = contraption.getSeatOf(id);
|
||||||
|
if (seat == null)
|
||||||
|
return null;
|
||||||
|
Vec3d transformedVector =
|
||||||
|
toGlobalVector(new Vec3d(seat).add(.5, passenger.getYOffset() + ySize - .15f, .5), partialTicks)
|
||||||
|
.add(VecHelper.getCenterOf(BlockPos.ZERO))
|
||||||
|
.subtract(0.5, ySize, 0.5);
|
||||||
|
return transformedVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canFitPassenger(Entity p_184219_1_) {
|
||||||
|
if (p_184219_1_ instanceof OrientedContraptionEntity)
|
||||||
|
return true;
|
||||||
|
return contraption.getSeatMapping()
|
||||||
|
.size() < contraption.getSeats()
|
||||||
|
.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handlePlayerInteraction(PlayerEntity player, BlockPos localPos, Direction side,
|
||||||
|
Hand interactionHand) {
|
||||||
|
int indexOfSeat = contraption.getSeats()
|
||||||
|
.indexOf(localPos);
|
||||||
|
if (indexOfSeat == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Eject potential existing passenger
|
||||||
|
Entity toDismount = null;
|
||||||
|
for (Entry<UUID, Integer> entry : contraption.getSeatMapping()
|
||||||
|
.entrySet()) {
|
||||||
|
if (entry.getValue() != indexOfSeat)
|
||||||
|
continue;
|
||||||
|
for (Entity entity : getPassengers()) {
|
||||||
|
if (!entry.getKey()
|
||||||
|
.equals(entity.getUniqueID()))
|
||||||
|
continue;
|
||||||
|
if (entity instanceof PlayerEntity)
|
||||||
|
return false;
|
||||||
|
toDismount = entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toDismount != null && !world.isRemote) {
|
||||||
|
Vec3d transformedVector = getPassengerPosition(toDismount, 1);
|
||||||
|
toDismount.stopRiding();
|
||||||
|
if (transformedVector != null)
|
||||||
|
toDismount.setPositionAndUpdate(transformedVector.x, transformedVector.y, transformedVector.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world.isRemote)
|
||||||
|
return true;
|
||||||
|
addSittingPassenger(player, indexOfSeat);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3d toGlobalVector(Vec3d localVec, float partialTicks) {
|
||||||
|
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
||||||
|
localVec = localVec.subtract(rotationOffset);
|
||||||
|
localVec = applyRotation(localVec, partialTicks);
|
||||||
|
localVec = localVec.add(rotationOffset)
|
||||||
|
.add(getAnchorVec());
|
||||||
|
return localVec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3d toLocalVector(Vec3d globalVec, float partialTicks) {
|
||||||
|
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
||||||
|
globalVec = globalVec.subtract(getAnchorVec())
|
||||||
|
.subtract(rotationOffset);
|
||||||
|
globalVec = reverseRotation(globalVec, partialTicks);
|
||||||
|
globalVec = globalVec.add(rotationOffset);
|
||||||
|
return globalVec;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void tick() {
|
||||||
|
if (contraption == null) {
|
||||||
|
remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prevPosX = getX();
|
||||||
|
prevPosY = getY();
|
||||||
|
prevPosZ = getZ();
|
||||||
|
prevPosInvalid = false;
|
||||||
|
|
||||||
|
if (!initialized)
|
||||||
|
contraptionInitialize();
|
||||||
|
tickContraption();
|
||||||
|
super.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void tickContraption();
|
||||||
|
|
||||||
|
public abstract Vec3d applyRotation(Vec3d localPos, float partialTicks);
|
||||||
|
|
||||||
|
public abstract Vec3d reverseRotation(Vec3d localPos, float partialTicks);
|
||||||
|
|
||||||
|
public void tickActors() {
|
||||||
|
boolean stalledPreviously = contraption.stalled;
|
||||||
|
|
||||||
|
if (!world.isRemote)
|
||||||
|
contraption.stalled = false;
|
||||||
|
|
||||||
|
for (MutablePair<BlockInfo, MovementContext> pair : contraption.getActors()) {
|
||||||
|
MovementContext context = pair.right;
|
||||||
|
BlockInfo blockInfo = pair.left;
|
||||||
|
MovementBehaviour actor = AllMovementBehaviours.of(blockInfo.state);
|
||||||
|
|
||||||
|
Vec3d actorPosition = toGlobalVector(VecHelper.getCenterOf(blockInfo.pos)
|
||||||
|
.add(actor.getActiveAreaOffset(context)), 1);
|
||||||
|
BlockPos gridPosition = new BlockPos(actorPosition);
|
||||||
|
boolean newPosVisited =
|
||||||
|
!context.stall && shouldActorTrigger(context, blockInfo, actor, actorPosition, gridPosition);
|
||||||
|
|
||||||
|
context.rotation = v -> applyRotation(v, 1);
|
||||||
|
context.position = actorPosition;
|
||||||
|
|
||||||
|
Vec3d oldMotion = context.motion;
|
||||||
|
if (!actor.isActive(context))
|
||||||
|
continue;
|
||||||
|
if (newPosVisited && !context.stall) {
|
||||||
|
actor.visitNewPosition(context, gridPosition);
|
||||||
|
context.firstMovement = false;
|
||||||
|
}
|
||||||
|
if (!oldMotion.equals(context.motion))
|
||||||
|
actor.onSpeedChanged(context, oldMotion, context.motion);
|
||||||
|
actor.tick(context);
|
||||||
|
contraption.stalled |= context.stall;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Entity entity : getPassengers()) {
|
||||||
|
if (!(entity instanceof OrientedContraptionEntity))
|
||||||
|
continue;
|
||||||
|
if (!contraption.stabilizedSubContraptions.containsKey(entity.getUniqueID()))
|
||||||
|
continue;
|
||||||
|
OrientedContraptionEntity orientedCE = (OrientedContraptionEntity) entity;
|
||||||
|
if (orientedCE.contraption != null && orientedCE.contraption.stalled) {
|
||||||
|
contraption.stalled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!world.isRemote) {
|
||||||
|
if (!stalledPreviously && contraption.stalled)
|
||||||
|
onContraptionStalled();
|
||||||
|
dataManager.set(STALLED, contraption.stalled);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
contraption.stalled = isStalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onContraptionStalled() {
|
||||||
|
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||||
|
new ContraptionStallPacket(getEntityId(), getX(), getY(), getZ(), getStalledAngle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean shouldActorTrigger(MovementContext context, BlockInfo blockInfo, MovementBehaviour actor,
|
||||||
|
Vec3d actorPosition, BlockPos gridPosition) {
|
||||||
|
Vec3d previousPosition = context.position;
|
||||||
|
if (previousPosition == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
context.motion = actorPosition.subtract(previousPosition);
|
||||||
|
Vec3d relativeMotion = context.motion;
|
||||||
|
relativeMotion = reverseRotation(relativeMotion, 1);
|
||||||
|
context.relativeMotion = relativeMotion;
|
||||||
|
return !new BlockPos(previousPosition).equals(gridPosition)
|
||||||
|
|| context.relativeMotion.length() > 0 && context.firstMovement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void move(double x, double y, double z) {
|
||||||
|
setPosition(getX() + x, getY() + y, getZ() + z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3d getAnchorVec() {
|
||||||
|
return getPositionVec();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getYawOffset() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPosition(double x, double y, double z) {
|
||||||
|
super.setPosition(x, y, z);
|
||||||
|
if (contraption == null)
|
||||||
|
return;
|
||||||
|
AxisAlignedBB cbox = contraption.bounds;
|
||||||
|
if (cbox == null)
|
||||||
|
return;
|
||||||
|
Vec3d actualVec = getAnchorVec();
|
||||||
|
setBoundingBox(cbox.offset(actualVec));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float yawFromVector(Vec3d vec) {
|
||||||
|
return (float) ((3 * Math.PI / 2 + Math.atan2(vec.z, vec.x)) / Math.PI * 180);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float pitchFromVector(Vec3d vec) {
|
||||||
|
return (float) ((Math.acos(vec.y)) / Math.PI * 180);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
EntityType.Builder<AbstractContraptionEntity> entityBuilder =
|
||||||
|
(EntityType.Builder<AbstractContraptionEntity>) builder;
|
||||||
|
return entityBuilder.size(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerData() {
|
||||||
|
this.dataManager.register(STALLED, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void readAdditional(CompoundNBT compound) {
|
||||||
|
initialized = compound.getBoolean("Initialized");
|
||||||
|
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
|
||||||
|
contraption.entity = this;
|
||||||
|
dataManager.set(STALLED, compound.getBoolean("Stalled"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeAdditional(CompoundNBT compound) {
|
||||||
|
if (contraption != null)
|
||||||
|
compound.put("Contraption", contraption.writeNBT());
|
||||||
|
compound.putBoolean("Stalled", isStalled());
|
||||||
|
compound.putBoolean("Initialized", initialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPacket<?> createSpawnPacket() {
|
||||||
|
return NetworkHooks.getEntitySpawningPacket(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeSpawnData(PacketBuffer buffer) {
|
||||||
|
CompoundNBT compound = new CompoundNBT();
|
||||||
|
writeAdditional(compound);
|
||||||
|
buffer.writeCompoundTag(compound);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readSpawnData(PacketBuffer additionalData) {
|
||||||
|
readAdditional(additionalData.readCompoundTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disassemble() {
|
||||||
|
if (!isAlive())
|
||||||
|
return;
|
||||||
|
if (contraption == null)
|
||||||
|
return;
|
||||||
|
remove();
|
||||||
|
StructureTransform transform = makeStructureTransform();
|
||||||
|
contraption.addBlocksToWorld(world, transform);
|
||||||
|
contraption.addPassengersToWorld(world, transform, getPassengers());
|
||||||
|
|
||||||
|
for (Entity entity : getPassengers()) {
|
||||||
|
if (!(entity instanceof OrientedContraptionEntity))
|
||||||
|
continue;
|
||||||
|
UUID id = entity.getUniqueID();
|
||||||
|
if (!contraption.stabilizedSubContraptions.containsKey(id))
|
||||||
|
continue;
|
||||||
|
BlockPos transformed = transform.apply(contraption.stabilizedSubContraptions.get(id)
|
||||||
|
.getConnectedPos());
|
||||||
|
entity.setPosition(transformed.getX(), transformed.getY(), transformed.getZ());
|
||||||
|
((AbstractContraptionEntity) entity).disassemble();
|
||||||
|
}
|
||||||
|
|
||||||
|
removePassengers();
|
||||||
|
|
||||||
|
for (Entity entity : collidingEntities) {
|
||||||
|
Vec3d positionVec = getPositionVec();
|
||||||
|
Vec3d localVec = entity.getPositionVec()
|
||||||
|
.subtract(positionVec);
|
||||||
|
localVec = reverseRotation(localVec, 1);
|
||||||
|
Vec3d transformed = transform.apply(localVec);
|
||||||
|
entity.setPositionAndUpdate(transformed.x, transformed.y, transformed.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract StructureTransform makeStructureTransform();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onKillCommand() {
|
||||||
|
removePassengers();
|
||||||
|
super.onKillCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void outOfWorld() {
|
||||||
|
removePassengers();
|
||||||
|
super.outOfWorld();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRemovedFromWorld() {
|
||||||
|
super.onRemovedFromWorld();
|
||||||
|
if (world != null && world.isRemote)
|
||||||
|
return;
|
||||||
|
getPassengers().forEach(Entity::remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doWaterSplashEffect() {}
|
||||||
|
|
||||||
|
public Contraption getContraption() {
|
||||||
|
return contraption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStalled() {
|
||||||
|
return dataManager.get(STALLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
static void handleStallPacket(ContraptionStallPacket packet) {
|
||||||
|
Entity entity = Minecraft.getInstance().world.getEntityByID(packet.entityID);
|
||||||
|
if (!(entity instanceof AbstractContraptionEntity))
|
||||||
|
return;
|
||||||
|
AbstractContraptionEntity ce = (AbstractContraptionEntity) entity;
|
||||||
|
ce.handleStallInformation(packet.x, packet.y, packet.z, packet.angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract float getStalledAngle();
|
||||||
|
|
||||||
|
protected abstract void handleStallInformation(float x, float y, float z, float angle);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public CompoundNBT writeWithoutTypeId(CompoundNBT nbt) {
|
||||||
|
Vec3d vec = getPositionVec();
|
||||||
|
List<Entity> passengers = getPassengers();
|
||||||
|
|
||||||
|
for (Entity entity : passengers) {
|
||||||
|
// setPos has world accessing side-effects when removed == false
|
||||||
|
entity.removed = true;
|
||||||
|
|
||||||
|
// Gather passengers into same chunk when saving
|
||||||
|
Vec3d prevVec = entity.getPositionVec();
|
||||||
|
entity.setPos(vec.x, prevVec.y, vec.z);
|
||||||
|
|
||||||
|
// Super requires all passengers to not be removed in order to write them to the
|
||||||
|
// tag
|
||||||
|
entity.removed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundNBT tag = super.writeWithoutTypeId(nbt);
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// Make sure nothing can move contraptions out of the way
|
||||||
|
public void setMotion(Vec3d motionIn) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PushReaction getPushReaction() {
|
||||||
|
return PushReaction.IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContraptionMotion(Vec3d vec) {
|
||||||
|
super.setMotion(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeCollidedWith() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean attackEntityFrom(DamageSource source, float amount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3d getPrevPositionVec() {
|
||||||
|
return prevPosInvalid ? getPositionVec() : new Vec3d(prevPosX, prevPosY, prevPosZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract ContraptionRotationState getRotationState();
|
||||||
|
|
||||||
|
public Vec3d getContactPointMotion(Vec3d globalContactPoint) {
|
||||||
|
if (prevPosInvalid)
|
||||||
|
return Vec3d.ZERO;
|
||||||
|
Vec3d contactPoint = toGlobalVector(toLocalVector(globalContactPoint, 0), 1);
|
||||||
|
return contactPoint.subtract(globalContactPoint)
|
||||||
|
.add(getPositionVec().subtract(getPrevPositionVec()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canCollideWith(Entity e) {
|
||||||
|
if (e instanceof PlayerEntity && e.isSpectator())
|
||||||
|
return false;
|
||||||
|
if (e.noClip)
|
||||||
|
return false;
|
||||||
|
if (e instanceof HangingEntity)
|
||||||
|
return false;
|
||||||
|
if (e instanceof AbstractMinecartEntity)
|
||||||
|
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) {
|
||||||
|
if (riding == e)
|
||||||
|
return false;
|
||||||
|
riding = riding.getRidingEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.getPushReaction() == PushReaction.NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOnePlayerRiding() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ContraptionRotationState {
|
||||||
|
static final ContraptionRotationState NONE = new ContraptionRotationState();
|
||||||
|
|
||||||
|
float xRotation = 0;
|
||||||
|
float yRotation = 0;
|
||||||
|
float zRotation = 0;
|
||||||
|
float secondYRotation = 0;
|
||||||
|
Matrix3d matrix;
|
||||||
|
|
||||||
|
public Matrix3d asMatrix() {
|
||||||
|
if (matrix != null)
|
||||||
|
return matrix;
|
||||||
|
|
||||||
|
matrix = new Matrix3d().asIdentity();
|
||||||
|
if (xRotation != 0)
|
||||||
|
matrix.multiply(new Matrix3d().asXRotation(AngleHelper.rad(-xRotation)));
|
||||||
|
if (yRotation != 0)
|
||||||
|
matrix.multiply(new Matrix3d().asYRotation(AngleHelper.rad(yRotation)));
|
||||||
|
if (zRotation != 0)
|
||||||
|
matrix.multiply(new Matrix3d().asZRotation(AngleHelper.rad(-zRotation)));
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasVerticalRotation() {
|
||||||
|
return xRotation != 0 || zRotation != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getYawOffset() {
|
||||||
|
return secondYRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
|
import net.minecraft.client.renderer.culling.ClippingHelperImpl;
|
||||||
|
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||||
|
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
|
public abstract class AbstractContraptionEntityRenderer<C extends AbstractContraptionEntity> extends EntityRenderer<C> {
|
||||||
|
|
||||||
|
protected AbstractContraptionEntityRenderer(EntityRendererManager p_i46179_1_) {
|
||||||
|
super(p_i46179_1_);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceLocation getEntityTexture(C p_110775_1_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void transform(C contraptionEntity, float partialTicks, MatrixStack[] matrixStacks);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRender(C entity, ClippingHelperImpl p_225626_2_, double p_225626_3_, double p_225626_5_,
|
||||||
|
double p_225626_7_) {
|
||||||
|
if (!super.shouldRender(entity, p_225626_2_, p_225626_3_, p_225626_5_, p_225626_7_))
|
||||||
|
return false;
|
||||||
|
if (!entity.isAlive())
|
||||||
|
return false;
|
||||||
|
if (entity.getContraption() == null)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(C entity, float yaw, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffers,
|
||||||
|
int overlay) {
|
||||||
|
super.render(entity, yaw, partialTicks, ms, buffers, overlay);
|
||||||
|
|
||||||
|
// Keep a copy of the transforms in order to determine correct lighting
|
||||||
|
MatrixStack msLocal = getLocalTransform(entity);
|
||||||
|
MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal };
|
||||||
|
|
||||||
|
ms.push();
|
||||||
|
transform(entity, partialTicks, matrixStacks);
|
||||||
|
ContraptionRenderer.render(entity.world, entity.getContraption(), ms, msLocal, buffers);
|
||||||
|
ms.pop();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MatrixStack getLocalTransform(AbstractContraptionEntity entity) {
|
||||||
|
double pt = Minecraft.getInstance()
|
||||||
|
.getRenderPartialTicks();
|
||||||
|
MatrixStack matrixStack = new MatrixStack();
|
||||||
|
double x = MathHelper.lerp(pt, entity.lastTickPosX, entity.getX());
|
||||||
|
double y = MathHelper.lerp(pt, entity.lastTickPosY, entity.getY());
|
||||||
|
double z = MathHelper.lerp(pt, entity.lastTickPosZ, entity.getZ());
|
||||||
|
matrixStack.translate(x, y, z);
|
||||||
|
return matrixStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import java.util.function.Supplier;
|
||||||
|
|
||||||
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.bearing.ClockworkContraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkContraption;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedContraption;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonContraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonContraption;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyContraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyContraption;
|
||||||
|
@ -16,6 +17,7 @@ public enum AllContraptionTypes {
|
||||||
PULLEY(PulleyContraption::new),
|
PULLEY(PulleyContraption::new),
|
||||||
CLOCKWORK(ClockworkContraption::new),
|
CLOCKWORK(ClockworkContraption::new),
|
||||||
MOUNTED(MountedContraption::new),
|
MOUNTED(MountedContraption::new),
|
||||||
|
STABILIZED(StabilizedContraption::new),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -28,10 +30,9 @@ public enum AllContraptionTypes {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Contraption fromType(String type) {
|
public static Contraption fromType(String type) {
|
||||||
for (AllContraptionTypes allContraptionTypes : values()) {
|
for (AllContraptionTypes allContraptionTypes : values())
|
||||||
if (type.equals(allContraptionTypes.id))
|
if (type.equals(allContraptionTypes.id))
|
||||||
return allContraptionTypes.factory.get();
|
return allContraptionTypes.factory.get();
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,6 +194,8 @@ public class BlockMovementTraits {
|
||||||
public static boolean notSupportive(BlockState state, Direction facing) {
|
public static boolean notSupportive(BlockState state, Direction facing) {
|
||||||
if (AllBlocks.MECHANICAL_DRILL.has(state))
|
if (AllBlocks.MECHANICAL_DRILL.has(state))
|
||||||
return state.get(BlockStateProperties.FACING) == facing;
|
return state.get(BlockStateProperties.FACING) == facing;
|
||||||
|
if (AllBlocks.MECHANICAL_BEARING.has(state))
|
||||||
|
return state.get(BlockStateProperties.FACING) == facing;
|
||||||
if (AllBlocks.CART_ASSEMBLER.has(state))
|
if (AllBlocks.CART_ASSEMBLER.has(state))
|
||||||
return Direction.DOWN == facing;
|
return Direction.DOWN == facing;
|
||||||
if (AllBlocks.MECHANICAL_SAW.has(state))
|
if (AllBlocks.MECHANICAL_SAW.has(state))
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
@ -25,6 +26,8 @@ import com.simibubi.create.AllMovementBehaviours;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
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.SeatBlock;
|
||||||
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
|
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedContraption;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock;
|
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisTileEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
|
||||||
|
@ -40,6 +43,7 @@ import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
|
||||||
import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateBlock;
|
import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateBlock;
|
||||||
import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock;
|
import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
import com.simibubi.create.foundation.utility.BlockFace;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
@ -54,8 +58,6 @@ import net.minecraft.block.DoorBlock;
|
||||||
import net.minecraft.block.IWaterLoggable;
|
import net.minecraft.block.IWaterLoggable;
|
||||||
import net.minecraft.block.PressurePlateBlock;
|
import net.minecraft.block.PressurePlateBlock;
|
||||||
import net.minecraft.block.SlimeBlock;
|
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.entity.Entity;
|
||||||
import net.minecraft.fluid.Fluids;
|
import net.minecraft.fluid.Fluids;
|
||||||
import net.minecraft.fluid.IFluidState;
|
import net.minecraft.fluid.IFluidState;
|
||||||
|
@ -83,54 +85,58 @@ import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||||
|
|
||||||
public abstract class Contraption {
|
public abstract class Contraption {
|
||||||
|
|
||||||
public Map<BlockPos, BlockInfo> blocks;
|
public AbstractContraptionEntity entity;
|
||||||
public Map<BlockPos, MountedStorage> storage;
|
|
||||||
public List<MutablePair<BlockInfo, MovementContext>> actors;
|
|
||||||
public CombinedInvWrapper inventory;
|
public CombinedInvWrapper inventory;
|
||||||
public List<TileEntity> customRenderTEs;
|
|
||||||
public Set<Pair<BlockPos, Direction>> superglue;
|
|
||||||
public ContraptionEntity entity;
|
|
||||||
|
|
||||||
public AxisAlignedBB bounds;
|
public AxisAlignedBB bounds;
|
||||||
|
public BlockPos anchor;
|
||||||
public boolean stalled;
|
public boolean stalled;
|
||||||
|
|
||||||
|
protected Map<BlockPos, BlockInfo> blocks;
|
||||||
|
protected Map<BlockPos, MountedStorage> storage;
|
||||||
|
protected List<MutablePair<BlockInfo, MovementContext>> actors;
|
||||||
|
protected Set<Pair<BlockPos, Direction>> superglue;
|
||||||
protected List<BlockPos> seats;
|
protected List<BlockPos> seats;
|
||||||
protected Map<UUID, Integer> seatMapping;
|
protected Map<UUID, Integer> seatMapping;
|
||||||
protected Map<BlockPos, Entity> initialPassengers;
|
protected Map<UUID, BlockFace> stabilizedSubContraptions;
|
||||||
|
|
||||||
protected Set<BlockPos> cachedColliders;
|
private List<SuperGlueEntity> glueToRemove;
|
||||||
protected Direction cachedColliderDirection;
|
private Map<BlockPos, Entity> initialPassengers;
|
||||||
protected BlockPos anchor;
|
private List<BlockFace> pendingSubContraptions;
|
||||||
protected List<SuperGlueEntity> glueToRemove;
|
|
||||||
List<BlockPos> renderOrder;
|
// Client
|
||||||
|
public List<TileEntity> renderedTileEntities;
|
||||||
|
|
||||||
public Contraption() {
|
public Contraption() {
|
||||||
blocks = new HashMap<>();
|
blocks = new HashMap<>();
|
||||||
storage = new HashMap<>();
|
storage = new HashMap<>();
|
||||||
actors = new ArrayList<>();
|
|
||||||
seats = new ArrayList<>();
|
seats = new ArrayList<>();
|
||||||
seatMapping = new HashMap<>();
|
actors = new ArrayList<>();
|
||||||
initialPassengers = new HashMap<>();
|
|
||||||
superglue = new HashSet<>();
|
superglue = new HashSet<>();
|
||||||
renderOrder = new ArrayList<>();
|
seatMapping = new HashMap<>();
|
||||||
customRenderTEs = new ArrayList<>();
|
|
||||||
glueToRemove = new ArrayList<>();
|
glueToRemove = new ArrayList<>();
|
||||||
|
initialPassengers = new HashMap<>();
|
||||||
|
renderedTileEntities = new ArrayList<>();
|
||||||
|
pendingSubContraptions = new ArrayList<>();
|
||||||
|
stabilizedSubContraptions = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static boolean isChassis(BlockState state) {
|
public abstract boolean assemble(World world, BlockPos pos);
|
||||||
return state.getBlock() instanceof AbstractChassisBlock;
|
|
||||||
|
protected abstract boolean canAxisBeStabilized(Axis axis);
|
||||||
|
|
||||||
|
protected abstract AllContraptionTypes getType();
|
||||||
|
|
||||||
|
protected boolean customBlockPlacement(IWorld world, BlockPos pos, BlockState state) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompoundNBT getTileEntityNBT(World world, BlockPos pos) {
|
protected boolean customBlockRemoval(IWorld world, BlockPos pos, BlockState state) {
|
||||||
TileEntity tileentity = world.getTileEntity(pos);
|
return false;
|
||||||
CompoundNBT compoundnbt = null;
|
|
||||||
if (tileentity != null) {
|
|
||||||
compoundnbt = tileentity.write(new CompoundNBT());
|
|
||||||
compoundnbt.remove("x");
|
|
||||||
compoundnbt.remove("y");
|
|
||||||
compoundnbt.remove("z");
|
|
||||||
}
|
}
|
||||||
return compoundnbt;
|
|
||||||
|
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection,
|
||||||
|
List<BlockPos> frontier) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Contraption fromNBT(World world, CompoundNBT nbt) {
|
public static Contraption fromNBT(World world, CompoundNBT nbt) {
|
||||||
|
@ -140,35 +146,6 @@ public abstract class Contraption {
|
||||||
return contraption;
|
return contraption;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static MovementBehaviour getMovement(BlockState state) {
|
|
||||||
Block block = state.getBlock();
|
|
||||||
if (!AllMovementBehaviours.hasMovementBehaviour(block))
|
|
||||||
return null;
|
|
||||||
return AllMovementBehaviours.getMovementBehaviour(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<BlockPos> getColliders(World world, Direction movementDirection) {
|
|
||||||
if (blocks == null)
|
|
||||||
return null;
|
|
||||||
if (cachedColliders == null || cachedColliderDirection != movementDirection) {
|
|
||||||
cachedColliders = new HashSet<>();
|
|
||||||
cachedColliderDirection = movementDirection;
|
|
||||||
|
|
||||||
for (BlockInfo info : blocks.values()) {
|
|
||||||
BlockPos offsetPos = info.pos.offset(movementDirection);
|
|
||||||
if (info.state.getCollisionShape(world, offsetPos)
|
|
||||||
.isEmpty())
|
|
||||||
continue;
|
|
||||||
if (blocks.containsKey(offsetPos) && !blocks.get(offsetPos).state.getCollisionShape(world, offsetPos)
|
|
||||||
.isEmpty())
|
|
||||||
continue;
|
|
||||||
cachedColliders.add(info.pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return cachedColliders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean searchMovedStructure(World world, BlockPos pos, @Nullable Direction forcedDirection) {
|
public boolean searchMovedStructure(World world, BlockPos pos, @Nullable Direction forcedDirection) {
|
||||||
initialPassengers.clear();
|
initialPassengers.clear();
|
||||||
List<BlockPos> frontier = new ArrayList<>();
|
List<BlockPos> frontier = new ArrayList<>();
|
||||||
|
@ -191,7 +168,27 @@ public abstract class Contraption {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gatherStoredItems() {
|
public void onEntityCreated(AbstractContraptionEntity entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
|
||||||
|
// Create subcontraptions
|
||||||
|
for (BlockFace blockFace : pendingSubContraptions) {
|
||||||
|
Direction face = blockFace.getFace();
|
||||||
|
StabilizedContraption subContraption = new StabilizedContraption(face);
|
||||||
|
World world = entity.world;
|
||||||
|
BlockPos pos = blockFace.getPos();
|
||||||
|
if (!subContraption.assemble(world, pos))
|
||||||
|
continue;
|
||||||
|
subContraption.removeBlocksFromWorld(world, BlockPos.ZERO);
|
||||||
|
OrientedContraptionEntity movedContraption =
|
||||||
|
OrientedContraptionEntity.create(world, subContraption, Optional.of(face));
|
||||||
|
BlockPos anchor = blockFace.getConnectedPos();
|
||||||
|
movedContraption.setPosition(anchor.getX() + .5f, anchor.getY(), anchor.getZ() + .5f);
|
||||||
|
world.addEntity(movedContraption);
|
||||||
|
stabilizedSubContraptions.put(movedContraption.getUniqueID(), new BlockFace(toLocalPos(pos), face));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gather itemhandlers of mounted storage
|
||||||
List<IItemHandlerModifiable> list = storage.values()
|
List<IItemHandlerModifiable> list = storage.values()
|
||||||
.stream()
|
.stream()
|
||||||
.map(MountedStorage::getItemHandler)
|
.map(MountedStorage::getItemHandler)
|
||||||
|
@ -199,10 +196,16 @@ public abstract class Contraption {
|
||||||
inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
|
inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mountPassengers(ContraptionEntity contraptionEntity) {
|
public void onEntityInitialize(World world, AbstractContraptionEntity contraptionEntity) {
|
||||||
this.entity = contraptionEntity;
|
if (world.isRemote)
|
||||||
if (contraptionEntity.world.isRemote)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
for (OrientedContraptionEntity orientedCE : world.getEntitiesWithinAABB(OrientedContraptionEntity.class,
|
||||||
|
contraptionEntity.getBoundingBox()
|
||||||
|
.grow(1)))
|
||||||
|
if (stabilizedSubContraptions.containsKey(orientedCE.getUniqueID()))
|
||||||
|
orientedCE.startRiding(contraptionEntity);
|
||||||
|
|
||||||
for (BlockPos seatPos : getSeats()) {
|
for (BlockPos seatPos : getSeats()) {
|
||||||
Entity passenger = initialPassengers.get(seatPos);
|
Entity passenger = initialPassengers.get(seatPos);
|
||||||
if (passenger == null)
|
if (passenger == null)
|
||||||
|
@ -214,11 +217,6 @@ public abstract class Contraption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection,
|
|
||||||
List<BlockPos> frontier) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean moveBlock(World world, BlockPos pos, Direction forcedDirection, List<BlockPos> frontier,
|
protected boolean moveBlock(World world, BlockPos pos, Direction forcedDirection, List<BlockPos> frontier,
|
||||||
Set<BlockPos> visited) {
|
Set<BlockPos> visited) {
|
||||||
visited.add(pos);
|
visited.add(pos);
|
||||||
|
@ -233,12 +231,88 @@ public abstract class Contraption {
|
||||||
if (!movementAllowed(world, pos))
|
if (!movementAllowed(world, pos))
|
||||||
return false;
|
return false;
|
||||||
BlockState state = world.getBlockState(pos);
|
BlockState state = world.getBlockState(pos);
|
||||||
if (isChassis(state) && !moveChassis(world, pos, forcedDirection, frontier, visited))
|
if (state.getBlock() instanceof AbstractChassisBlock
|
||||||
|
&& !moveChassis(world, pos, forcedDirection, frontier, visited))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (AllBlocks.ADJUSTABLE_CRATE.has(state))
|
if (AllBlocks.ADJUSTABLE_CRATE.has(state))
|
||||||
AdjustableCrateBlock.splitCrate(world, pos);
|
AdjustableCrateBlock.splitCrate(world, pos);
|
||||||
if (AllBlocks.BELT.has(state)) {
|
|
||||||
|
if (AllBlocks.BELT.has(state))
|
||||||
|
moveBelt(pos, frontier, visited, state);
|
||||||
|
|
||||||
|
// Bearings potentially create stabilized sub-contraptions
|
||||||
|
if (AllBlocks.MECHANICAL_BEARING.has(state))
|
||||||
|
moveBearing(pos, frontier, visited, state);
|
||||||
|
|
||||||
|
// Seats transfer their passenger to the contraption
|
||||||
|
if (state.getBlock() instanceof SeatBlock)
|
||||||
|
moveSeat(world, pos);
|
||||||
|
|
||||||
|
// Pulleys drag their rope and their attached structure
|
||||||
|
if (state.getBlock() instanceof PulleyBlock)
|
||||||
|
movePulley(world, pos, frontier, visited);
|
||||||
|
|
||||||
|
// Pistons drag their attaches poles and extension
|
||||||
|
if (state.getBlock() instanceof MechanicalPistonBlock)
|
||||||
|
if (!moveMechanicalPiston(world, pos, frontier, visited, state))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Doors try to stay whole
|
||||||
|
if (state.getBlock() instanceof DoorBlock) {
|
||||||
|
BlockPos otherPartPos = pos.up(state.get(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? 1 : -1);
|
||||||
|
if (!visited.contains(otherPartPos))
|
||||||
|
frontier.add(otherPartPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cart assemblers attach themselves
|
||||||
|
BlockState stateBelow = world.getBlockState(pos.down());
|
||||||
|
if (!visited.contains(pos.down()) && AllBlocks.CART_ASSEMBLER.has(stateBelow))
|
||||||
|
frontier.add(pos.down());
|
||||||
|
|
||||||
|
Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos);
|
||||||
|
|
||||||
|
// Slime blocks and super glue drag adjacent blocks if possible
|
||||||
|
boolean isSlimeBlock = state.getBlock() instanceof SlimeBlock;
|
||||||
|
for (Direction offset : Direction.values()) {
|
||||||
|
BlockPos offsetPos = pos.offset(offset);
|
||||||
|
BlockState blockState = world.getBlockState(offsetPos);
|
||||||
|
if (isAnchoringBlockAt(offsetPos))
|
||||||
|
continue;
|
||||||
|
if (!movementAllowed(world, offsetPos)) {
|
||||||
|
if (offset == forcedDirection && isSlimeBlock)
|
||||||
|
return false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean wasVisited = visited.contains(offsetPos);
|
||||||
|
boolean faceHasGlue = superglue.containsKey(offset);
|
||||||
|
boolean blockAttachedTowardsFace =
|
||||||
|
BlockMovementTraits.isBlockAttachedTowards(blockState, offset.getOpposite());
|
||||||
|
boolean brittle = BlockMovementTraits.isBrittle(blockState);
|
||||||
|
|
||||||
|
if (!wasVisited && ((isSlimeBlock && !brittle) || blockAttachedTowardsFace || faceHasGlue))
|
||||||
|
frontier.add(offsetPos);
|
||||||
|
if (faceHasGlue)
|
||||||
|
addGlue(superglue.get(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
addBlock(pos, capture(world, pos));
|
||||||
|
return blocks.size() <= AllConfigs.SERVER.kinetics.maxBlocksMoved.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveBearing(BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, BlockState state) {
|
||||||
|
Direction facing = state.get(MechanicalBearingBlock.FACING);
|
||||||
|
if (!canAxisBeStabilized(facing.getAxis())) {
|
||||||
|
BlockPos offset = pos.offset(facing);
|
||||||
|
if (!visited.contains(offset))
|
||||||
|
frontier.add(offset);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pendingSubContraptions.add(new BlockFace(pos, facing));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveBelt(BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, BlockState state) {
|
||||||
BlockPos nextPos = BeltBlock.nextSegmentPosition(state, pos, true);
|
BlockPos nextPos = BeltBlock.nextSegmentPosition(state, pos, true);
|
||||||
BlockPos prevPos = BeltBlock.nextSegmentPosition(state, pos, false);
|
BlockPos prevPos = BeltBlock.nextSegmentPosition(state, pos, false);
|
||||||
if (nextPos != null && !visited.contains(nextPos))
|
if (nextPos != null && !visited.contains(nextPos))
|
||||||
|
@ -247,8 +321,7 @@ public abstract class Contraption {
|
||||||
frontier.add(prevPos);
|
frontier.add(prevPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seats transfer their passenger to the contraption
|
private void moveSeat(World world, BlockPos pos) {
|
||||||
if (state.getBlock() instanceof SeatBlock) {
|
|
||||||
BlockPos local = toLocalPos(pos);
|
BlockPos local = toLocalPos(pos);
|
||||||
getSeats().add(local);
|
getSeats().add(local);
|
||||||
List<SeatEntity> seatsEntities = world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos));
|
List<SeatEntity> seatsEntities = world.getEntitiesWithinAABB(SeatEntity.class, new AxisAlignedBB(pos));
|
||||||
|
@ -260,8 +333,7 @@ public abstract class Contraption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pulleys drag their rope and their attached structure
|
private void movePulley(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited) {
|
||||||
if (state.getBlock() instanceof PulleyBlock) {
|
|
||||||
int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get();
|
int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get();
|
||||||
BlockPos ropePos = pos;
|
BlockPos ropePos = pos;
|
||||||
while (limit-- >= 0) {
|
while (limit-- >= 0) {
|
||||||
|
@ -275,12 +347,12 @@ public abstract class Contraption {
|
||||||
frontier.add(ropePos);
|
frontier.add(ropePos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
add(ropePos, capture(world, ropePos));
|
addBlock(ropePos, capture(world, ropePos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pistons drag their attaches poles and extension
|
private boolean moveMechanicalPiston(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited,
|
||||||
if (state.getBlock() instanceof MechanicalPistonBlock) {
|
BlockState state) {
|
||||||
int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get();
|
int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get();
|
||||||
Direction direction = state.get(MechanicalPistonBlock.FACING);
|
Direction direction = state.get(MechanicalPistonBlock.FACING);
|
||||||
if (state.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) {
|
if (state.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) {
|
||||||
|
@ -322,57 +394,7 @@ public abstract class Contraption {
|
||||||
|
|
||||||
if (limit <= -1)
|
if (limit <= -1)
|
||||||
return false;
|
return false;
|
||||||
}
|
return true;
|
||||||
|
|
||||||
// Doors try to stay whole
|
|
||||||
if (state.getBlock() instanceof DoorBlock) {
|
|
||||||
BlockPos otherPartPos = pos.up(state.get(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? 1 : -1);
|
|
||||||
if (!visited.contains(otherPartPos))
|
|
||||||
frontier.add(otherPartPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cart assemblers attach themselves
|
|
||||||
BlockState stateBelow = world.getBlockState(pos.down());
|
|
||||||
if (!visited.contains(pos.down()) && AllBlocks.CART_ASSEMBLER.has(stateBelow))
|
|
||||||
frontier.add(pos.down());
|
|
||||||
|
|
||||||
Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos);
|
|
||||||
|
|
||||||
// Slime blocks and super glue drag adjacent blocks if possible
|
|
||||||
boolean isSlimeBlock = state.getBlock() instanceof SlimeBlock;
|
|
||||||
for (Direction offset : Direction.values()) {
|
|
||||||
BlockPos offsetPos = pos.offset(offset);
|
|
||||||
BlockState blockState = world.getBlockState(offsetPos);
|
|
||||||
if (isAnchoringBlockAt(offsetPos))
|
|
||||||
continue;
|
|
||||||
if (!movementAllowed(world, offsetPos)) {
|
|
||||||
if (offset == forcedDirection && isSlimeBlock)
|
|
||||||
return false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean wasVisited = visited.contains(offsetPos);
|
|
||||||
boolean faceHasGlue = superglue.containsKey(offset);
|
|
||||||
boolean blockAttachedTowardsFace =
|
|
||||||
BlockMovementTraits.isBlockAttachedTowards(blockState, offset.getOpposite());
|
|
||||||
boolean brittle = BlockMovementTraits.isBrittle(blockState);
|
|
||||||
|
|
||||||
if (!wasVisited && ((isSlimeBlock && !brittle) || blockAttachedTowardsFace || faceHasGlue))
|
|
||||||
frontier.add(offsetPos);
|
|
||||||
if (faceHasGlue)
|
|
||||||
addGlue(superglue.get(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
add(pos, capture(world, pos));
|
|
||||||
return blocks.size() <= AllConfigs.SERVER.kinetics.maxBlocksMoved.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean movementAllowed(World world, BlockPos pos) {
|
|
||||||
return BlockMovementTraits.movementAllowed(world, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isAnchoringBlockAt(BlockPos pos) {
|
|
||||||
return pos.equals(anchor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean moveChassis(World world, BlockPos pos, Direction movementDirection, List<BlockPos> frontier,
|
private boolean moveChassis(World world, BlockPos pos, Direction movementDirection, List<BlockPos> frontier,
|
||||||
|
@ -414,18 +436,7 @@ public abstract class Contraption {
|
||||||
return Pair.of(new BlockInfo(pos, blockstate, compoundnbt), tileentity);
|
return Pair.of(new BlockInfo(pos, blockstate, compoundnbt), tileentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addGlue(SuperGlueEntity entity) {
|
protected void addBlock(BlockPos pos, Pair<BlockInfo, TileEntity> pair) {
|
||||||
BlockPos pos = entity.getHangingPosition();
|
|
||||||
Direction direction = entity.getFacingDirection();
|
|
||||||
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();
|
BlockInfo captured = pair.getKey();
|
||||||
BlockPos localPos = pos.subtract(anchor);
|
BlockPos localPos = pos.subtract(anchor);
|
||||||
BlockInfo blockInfo = new BlockInfo(localPos, captured.state, captured.nbt);
|
BlockInfo blockInfo = new BlockInfo(localPos, captured.state, captured.nbt);
|
||||||
|
@ -437,14 +448,44 @@ public abstract class Contraption {
|
||||||
TileEntity te = pair.getValue();
|
TileEntity te = pair.getValue();
|
||||||
if (te != null && MountedStorage.canUseAsStorage(te))
|
if (te != null && MountedStorage.canUseAsStorage(te))
|
||||||
storage.put(localPos, new MountedStorage(te));
|
storage.put(localPos, new MountedStorage(te));
|
||||||
if (AllMovementBehaviours.hasMovementBehaviour(captured.state.getBlock()))
|
if (AllMovementBehaviours.contains(captured.state.getBlock()))
|
||||||
actors.add(MutablePair.of(blockInfo, null));
|
actors.add(MutablePair.of(blockInfo, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected CompoundNBT getTileEntityNBT(World world, BlockPos pos) {
|
||||||
|
TileEntity tileentity = world.getTileEntity(pos);
|
||||||
|
if (tileentity == null)
|
||||||
|
return null;
|
||||||
|
CompoundNBT nbt = tileentity.write(new CompoundNBT());
|
||||||
|
nbt.remove("x");
|
||||||
|
nbt.remove("y");
|
||||||
|
nbt.remove("z");
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addGlue(SuperGlueEntity entity) {
|
||||||
|
BlockPos pos = entity.getHangingPosition();
|
||||||
|
Direction direction = entity.getFacingDirection();
|
||||||
|
this.superglue.add(Pair.of(toLocalPos(pos), direction));
|
||||||
|
glueToRemove.add(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BlockPos toLocalPos(BlockPos globalPos) {
|
||||||
|
return globalPos.subtract(anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean movementAllowed(World world, BlockPos pos) {
|
||||||
|
return BlockMovementTraits.movementAllowed(world, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isAnchoringBlockAt(BlockPos pos) {
|
||||||
|
return pos.equals(anchor);
|
||||||
|
}
|
||||||
|
|
||||||
public void readNBT(World world, CompoundNBT nbt) {
|
public void readNBT(World world, CompoundNBT nbt) {
|
||||||
blocks.clear();
|
blocks.clear();
|
||||||
renderOrder.clear();
|
renderedTileEntities.clear();
|
||||||
customRenderTEs.clear();
|
|
||||||
|
|
||||||
nbt.getList("Blocks", 10)
|
nbt.getList("Blocks", 10)
|
||||||
.forEach(c -> {
|
.forEach(c -> {
|
||||||
|
@ -456,12 +497,8 @@ public abstract class Contraption {
|
||||||
|
|
||||||
if (world.isRemote) {
|
if (world.isRemote) {
|
||||||
Block block = info.state.getBlock();
|
Block block = info.state.getBlock();
|
||||||
if (RenderTypeLookup.canRenderInLayer(info.state, RenderType.getTranslucent()))
|
|
||||||
renderOrder.add(info.pos);
|
|
||||||
else
|
|
||||||
renderOrder.add(0, info.pos);
|
|
||||||
CompoundNBT tag = info.nbt;
|
CompoundNBT tag = info.nbt;
|
||||||
MovementBehaviour movementBehaviour = AllMovementBehaviours.getMovementBehaviour(block);
|
MovementBehaviour movementBehaviour = AllMovementBehaviours.of(block);
|
||||||
if (tag == null || (movementBehaviour != null && movementBehaviour.hasSpecialMovementRenderer()))
|
if (tag == null || (movementBehaviour != null && movementBehaviour.hasSpecialMovementRenderer()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -485,7 +522,7 @@ public abstract class Contraption {
|
||||||
if (te instanceof KineticTileEntity)
|
if (te instanceof KineticTileEntity)
|
||||||
((KineticTileEntity) te).setSpeed(0);
|
((KineticTileEntity) te).setSpeed(0);
|
||||||
te.getBlockState();
|
te.getBlockState();
|
||||||
customRenderTEs.add(te);
|
renderedTileEntities.add(te);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -494,8 +531,7 @@ public abstract class Contraption {
|
||||||
.forEach(c -> {
|
.forEach(c -> {
|
||||||
CompoundNBT comp = (CompoundNBT) c;
|
CompoundNBT comp = (CompoundNBT) c;
|
||||||
BlockInfo info = blocks.get(NBTUtil.readBlockPos(comp.getCompound("Pos")));
|
BlockInfo info = blocks.get(NBTUtil.readBlockPos(comp.getCompound("Pos")));
|
||||||
MovementContext context = MovementContext.readNBT(world, info, comp);
|
MovementContext context = MovementContext.readNBT(world, info, comp, this);
|
||||||
context.contraption = this;
|
|
||||||
getActors().add(MutablePair.of(info, context));
|
getActors().add(MutablePair.of(info, context));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -510,6 +546,10 @@ public abstract class Contraption {
|
||||||
NBTHelper.iterateCompoundList(nbt.getList("Passengers", NBT.TAG_COMPOUND),
|
NBTHelper.iterateCompoundList(nbt.getList("Passengers", NBT.TAG_COMPOUND),
|
||||||
c -> seatMapping.put(NBTUtil.readUniqueId(c.getCompound("Id")), c.getInt("Seat")));
|
c -> seatMapping.put(NBTUtil.readUniqueId(c.getCompound("Id")), c.getInt("Seat")));
|
||||||
|
|
||||||
|
stabilizedSubContraptions.clear();
|
||||||
|
NBTHelper.iterateCompoundList(nbt.getList("SubContraptions", NBT.TAG_COMPOUND), c -> stabilizedSubContraptions
|
||||||
|
.put(NBTUtil.readUniqueId(c.getCompound("Id")), BlockFace.fromNBT(c.getCompound("Location"))));
|
||||||
|
|
||||||
storage.clear();
|
storage.clear();
|
||||||
NBTHelper.iterateCompoundList(nbt.getList("Storage", NBT.TAG_COMPOUND), c -> storage
|
NBTHelper.iterateCompoundList(nbt.getList("Storage", NBT.TAG_COMPOUND), c -> storage
|
||||||
.put(NBTUtil.readBlockPos(c.getCompound("Pos")), MountedStorage.deserialize(c.getCompound("Data"))));
|
.put(NBTUtil.readBlockPos(c.getCompound("Pos")), MountedStorage.deserialize(c.getCompound("Data"))));
|
||||||
|
@ -544,7 +584,8 @@ public abstract class Contraption {
|
||||||
for (MutablePair<BlockInfo, MovementContext> actor : getActors()) {
|
for (MutablePair<BlockInfo, MovementContext> actor : getActors()) {
|
||||||
CompoundNBT compound = new CompoundNBT();
|
CompoundNBT compound = new CompoundNBT();
|
||||||
compound.put("Pos", NBTUtil.writeBlockPos(actor.left.pos));
|
compound.put("Pos", NBTUtil.writeBlockPos(actor.left.pos));
|
||||||
getMovement(actor.left.state).writeExtraData(actor.right);
|
AllMovementBehaviours.of(actor.left.state)
|
||||||
|
.writeExtraData(actor.right);
|
||||||
actor.right.writeToNBT(compound);
|
actor.right.writeToNBT(compound);
|
||||||
actorsNBT.add(compound);
|
actorsNBT.add(compound);
|
||||||
}
|
}
|
||||||
|
@ -577,6 +618,14 @@ public abstract class Contraption {
|
||||||
return tag;
|
return tag;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
nbt.put("SubContraptions", NBTHelper.writeCompoundList(stabilizedSubContraptions.entrySet(), e -> {
|
||||||
|
CompoundNBT tag = new CompoundNBT();
|
||||||
|
tag.put("Id", NBTUtil.writeUniqueId(e.getKey()));
|
||||||
|
tag.put("Location", e.getValue()
|
||||||
|
.serializeNBT());
|
||||||
|
return tag;
|
||||||
|
}));
|
||||||
|
|
||||||
nbt.put("Blocks", blocksNBT);
|
nbt.put("Blocks", blocksNBT);
|
||||||
nbt.put("Actors", actorsNBT);
|
nbt.put("Actors", actorsNBT);
|
||||||
nbt.put("Superglue", superglueNBT);
|
nbt.put("Superglue", superglueNBT);
|
||||||
|
@ -592,14 +641,6 @@ public abstract class Contraption {
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean customBlockPlacement(IWorld world, BlockPos pos, BlockState state) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean customBlockRemoval(IWorld world, BlockPos pos, BlockState state) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
|
public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
|
||||||
storage.values()
|
storage.values()
|
||||||
.forEach(MountedStorage::removeStorageFromWorld);
|
.forEach(MountedStorage::removeStorageFromWorld);
|
||||||
|
@ -732,27 +773,15 @@ public abstract class Contraption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initActors(World world) {
|
public void startMoving(World world) {
|
||||||
for (MutablePair<BlockInfo, MovementContext> pair : actors) {
|
for (MutablePair<BlockInfo, MovementContext> pair : actors) {
|
||||||
MovementContext context = new MovementContext(world, pair.left);
|
MovementContext context = new MovementContext(world, pair.left, this);
|
||||||
context.contraption = this;
|
AllMovementBehaviours.of(pair.left.state)
|
||||||
getMovement(pair.left.state).startMoving(context);
|
.startMoving(context);
|
||||||
pair.setRight(context);
|
pair.setRight(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AxisAlignedBB getBoundingBox() {
|
|
||||||
return bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MutablePair<BlockInfo, MovementContext>> getActors() {
|
|
||||||
return actors;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockPos getAnchor() {
|
|
||||||
return anchor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop(World world) {
|
public void stop(World world) {
|
||||||
foreachActor(world, (behaviour, ctx) -> {
|
foreachActor(world, (behaviour, ctx) -> {
|
||||||
behaviour.stopMoving(ctx);
|
behaviour.stopMoving(ctx);
|
||||||
|
@ -765,7 +794,7 @@ public abstract class Contraption {
|
||||||
|
|
||||||
public void foreachActor(World world, BiConsumer<MovementBehaviour, MovementContext> callBack) {
|
public void foreachActor(World world, BiConsumer<MovementBehaviour, MovementContext> callBack) {
|
||||||
for (MutablePair<BlockInfo, MovementContext> pair : actors)
|
for (MutablePair<BlockInfo, MovementContext> pair : actors)
|
||||||
callBack.accept(getMovement(pair.getLeft().state), pair.getRight());
|
callBack.accept(AllMovementBehaviours.of(pair.getLeft().state), pair.getRight());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void expandBoundsAroundAxis(Axis axis) {
|
public void expandBoundsAroundAxis(Axis axis) {
|
||||||
|
@ -792,7 +821,13 @@ public abstract class Contraption {
|
||||||
bounds = new AxisAlignedBB(min, max);
|
bounds = new AxisAlignedBB(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockPos getSeat(UUID entityId) {
|
public void addExtraInventories(Entity entity) {}
|
||||||
|
|
||||||
|
public Map<UUID, Integer> getSeatMapping() {
|
||||||
|
return seatMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPos getSeatOf(UUID entityId) {
|
||||||
if (!getSeatMapping().containsKey(entityId))
|
if (!getSeatMapping().containsKey(entityId))
|
||||||
return null;
|
return null;
|
||||||
int seatIndex = getSeatMapping().get(entityId);
|
int seatIndex = getSeatMapping().get(entityId);
|
||||||
|
@ -801,10 +836,11 @@ public abstract class Contraption {
|
||||||
return getSeats().get(seatIndex);
|
return getSeats().get(seatIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract AllContraptionTypes getType();
|
public BlockPos getBearingPosOf(UUID subContraptionEntityId) {
|
||||||
|
if (stabilizedSubContraptions.containsKey(subContraptionEntityId))
|
||||||
public Map<UUID, Integer> getSeatMapping() {
|
return stabilizedSubContraptions.get(subContraptionEntityId)
|
||||||
return seatMapping;
|
.getConnectedPos();
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSeatMapping(Map<UUID, Integer> seatMapping) {
|
public void setSeatMapping(Map<UUID, Integer> seatMapping) {
|
||||||
|
@ -815,5 +851,12 @@ public abstract class Contraption {
|
||||||
return seats;
|
return seats;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addExtraInventories(Entity entity) {};
|
public Map<BlockPos, BlockInfo> getBlocks() {
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MutablePair<BlockInfo, MovementContext>> getActors() {
|
||||||
|
return actors;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -15,12 +15,12 @@ import com.google.common.collect.ImmutableSet;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllMovementBehaviours;
|
import com.simibubi.create.AllMovementBehaviours;
|
||||||
import com.simibubi.create.content.contraptions.components.actors.BlockBreakingMovementBehaviour;
|
import com.simibubi.create.content.contraptions.components.actors.BlockBreakingMovementBehaviour;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity.ContraptionRotationState;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ClientMotionPacket;
|
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ClientMotionPacket;
|
||||||
import com.simibubi.create.foundation.collision.ContinuousOBBCollider.ContinuousSeparationManifold;
|
import com.simibubi.create.foundation.collision.ContinuousOBBCollider.ContinuousSeparationManifold;
|
||||||
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.networking.AllPackets;
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ import net.minecraft.block.CocoaBlock;
|
||||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
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.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
@ -55,38 +56,23 @@ public class ContraptionCollider {
|
||||||
NONE, CLIENT, REMOTE, SERVER
|
NONE, CLIENT, REMOTE, SERVER
|
||||||
}
|
}
|
||||||
|
|
||||||
static void collideEntities(ContraptionEntity contraptionEntity) {
|
static void collideEntities(AbstractContraptionEntity contraptionEntity) {
|
||||||
World world = contraptionEntity.getEntityWorld();
|
World world = contraptionEntity.getEntityWorld();
|
||||||
Contraption contraption = contraptionEntity.getContraption();
|
Contraption contraption = contraptionEntity.getContraption();
|
||||||
AxisAlignedBB bounds = contraptionEntity.getBoundingBox();
|
AxisAlignedBB bounds = contraptionEntity.getBoundingBox();
|
||||||
Vec3d contraptionPosition = contraptionEntity.getPositionVec();
|
|
||||||
Vec3d contraptionRotation = contraptionEntity.getRotationVec();
|
|
||||||
Vec3d contraptionMotion = contraptionEntity.stationary ? Vec3d.ZERO
|
|
||||||
: contraptionPosition.subtract(contraptionEntity.getPrevPositionVec());
|
|
||||||
contraptionEntity.collidingEntities.clear();
|
|
||||||
|
|
||||||
if (contraption == null)
|
if (contraption == null)
|
||||||
return;
|
return;
|
||||||
if (bounds == null)
|
if (bounds == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Vec3d centerOfBlock = VecHelper.getCenterOf(BlockPos.ZERO);
|
contraptionEntity.collidingEntities.clear();
|
||||||
double conRotX = contraptionRotation.x;
|
|
||||||
double conRotY = contraptionRotation.y + contraptionEntity.getInitialYaw();
|
|
||||||
double conRotZ = contraptionRotation.z;
|
|
||||||
|
|
||||||
double reverseYaw = 0;
|
Vec3d contraptionPosition = contraptionEntity.getPositionVec();
|
||||||
|
Vec3d contraptionMotion = contraptionPosition.subtract(contraptionEntity.getPrevPositionVec());
|
||||||
// Collision algorithm does not support rotation around two axes -> rotate
|
Vec3d anchorVec = contraptionEntity.getAnchorVec();
|
||||||
// entities manually
|
Vec3d centerOfBlock = VecHelper.CENTER_OF_ORIGIN;
|
||||||
if (conRotZ != 0 && contraptionRotation.y != 0) {
|
ContraptionRotationState rotation = null;
|
||||||
reverseYaw = contraptionRotation.y;
|
|
||||||
conRotY = contraptionEntity.getInitialYaw();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3d contraptionCentreOffset = contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0);
|
|
||||||
boolean axisAlignedCollision = contraptionRotation.equals(Vec3d.ZERO);
|
|
||||||
Matrix3d rotation = null;
|
|
||||||
|
|
||||||
for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, bounds.grow(2)
|
for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, bounds.grow(2)
|
||||||
.expand(0, 32, 0), contraptionEntity::canCollideWith)) {
|
.expand(0, 32, 0), contraptionEntity::canCollideWith)) {
|
||||||
|
@ -96,27 +82,23 @@ public class ContraptionCollider {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Init matrix
|
// Init matrix
|
||||||
if (rotation == null) {
|
if (rotation == null)
|
||||||
rotation = new Matrix3d().asIdentity();
|
rotation = contraptionEntity.getRotationState();
|
||||||
if (!axisAlignedCollision) {
|
Matrix3d rotationMatrix = rotation.asMatrix();
|
||||||
rotation.multiply(new Matrix3d().asXRotation(AngleHelper.rad(-conRotX)));
|
|
||||||
rotation.multiply(new Matrix3d().asYRotation(AngleHelper.rad(conRotY)));
|
|
||||||
rotation.multiply(new Matrix3d().asZRotation(AngleHelper.rad(-conRotZ)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform entity position and motion to local space
|
// Transform entity position and motion to local space
|
||||||
Vec3d entityPosition = entity.getPositionVec();
|
Vec3d entityPosition = entity.getPositionVec();
|
||||||
AxisAlignedBB entityBounds = entity.getBoundingBox();
|
AxisAlignedBB entityBounds = entity.getBoundingBox();
|
||||||
Vec3d centerY = new Vec3d(0, entityBounds.getYSize() / 2, 0);
|
Vec3d centerY = new Vec3d(0, entityBounds.getYSize() / 2, 0);
|
||||||
Vec3d motion = entity.getMotion();
|
Vec3d motion = entity.getMotion();
|
||||||
|
float yawOffset = rotation.getYawOffset();
|
||||||
|
|
||||||
Vec3d position = entityPosition;
|
Vec3d position = entityPosition;
|
||||||
position = position.subtract(contraptionCentreOffset);
|
|
||||||
position = position.add(centerY);
|
position = position.add(centerY);
|
||||||
position = position.subtract(contraptionPosition);
|
position = position.subtract(centerOfBlock);
|
||||||
position = VecHelper.rotate(position, -reverseYaw, Axis.Y);
|
position = position.subtract(anchorVec);
|
||||||
position = rotation.transform(position);
|
position = VecHelper.rotate(position, -yawOffset, Axis.Y);
|
||||||
|
position = rotationMatrix.transform(position);
|
||||||
position = position.add(centerOfBlock);
|
position = position.add(centerOfBlock);
|
||||||
position = position.subtract(centerY);
|
position = position.subtract(centerY);
|
||||||
position = position.subtract(entityPosition);
|
position = position.subtract(entityPosition);
|
||||||
|
@ -132,14 +114,10 @@ public class ContraptionCollider {
|
||||||
|
|
||||||
// Prepare entity bounds
|
// Prepare entity bounds
|
||||||
OrientedBB obb = new OrientedBB(localBB);
|
OrientedBB obb = new OrientedBB(localBB);
|
||||||
obb.setRotation(rotation);
|
obb.setRotation(rotationMatrix);
|
||||||
motion = rotation.transform(motion);
|
motion = rotationMatrix.transform(motion);
|
||||||
motion = motion.subtract(contraptionMotion);
|
motion = motion.subtract(contraptionMotion);
|
||||||
|
|
||||||
// Vec3d visualizerOrigin = new Vec3d(10, 64, 0);
|
|
||||||
// CollisionDebugger.OBB = obb.copy();
|
|
||||||
// CollisionDebugger.OBB.move(visualizerOrigin);
|
|
||||||
|
|
||||||
MutableObject<Vec3d> collisionResponse = new MutableObject<>(Vec3d.ZERO);
|
MutableObject<Vec3d> collisionResponse = new MutableObject<>(Vec3d.ZERO);
|
||||||
MutableObject<Vec3d> allowedMotion = new MutableObject<>(motion);
|
MutableObject<Vec3d> allowedMotion = new MutableObject<>(motion);
|
||||||
MutableBoolean futureCollision = new MutableBoolean(false);
|
MutableBoolean futureCollision = new MutableBoolean(false);
|
||||||
|
@ -152,7 +130,7 @@ public class ContraptionCollider {
|
||||||
.forEach(shape -> shape.toBoundingBoxList()
|
.forEach(shape -> shape.toBoundingBoxList()
|
||||||
.forEach(bbs::add));
|
.forEach(bbs::add));
|
||||||
|
|
||||||
boolean doHorizontalPass = conRotX == 0 && conRotZ == 0;
|
boolean doHorizontalPass = rotation.hasVerticalRotation();
|
||||||
for (boolean horizontalPass : Iterate.trueAndFalse) {
|
for (boolean horizontalPass : Iterate.trueAndFalse) {
|
||||||
|
|
||||||
for (AxisAlignedBB bb : bbs) {
|
for (AxisAlignedBB bb : bbs) {
|
||||||
|
@ -200,13 +178,12 @@ public class ContraptionCollider {
|
||||||
Vec3d motionResponse = allowedMotion.getValue();
|
Vec3d motionResponse = allowedMotion.getValue();
|
||||||
boolean hardCollision = !totalResponse.equals(Vec3d.ZERO);
|
boolean hardCollision = !totalResponse.equals(Vec3d.ZERO);
|
||||||
|
|
||||||
|
rotationMatrix.transpose();
|
||||||
rotation.transpose();
|
motionResponse = rotationMatrix.transform(motionResponse)
|
||||||
motionResponse = rotation.transform(motionResponse)
|
|
||||||
.add(contraptionMotion);
|
.add(contraptionMotion);
|
||||||
totalResponse = rotation.transform(totalResponse);
|
totalResponse = rotationMatrix.transform(totalResponse);
|
||||||
totalResponse = VecHelper.rotate(totalResponse, reverseYaw, Axis.Y);
|
totalResponse = VecHelper.rotate(totalResponse, yawOffset, Axis.Y);
|
||||||
rotation.transpose();
|
rotationMatrix.transpose();
|
||||||
|
|
||||||
if (futureCollision.isTrue() && playerType != PlayerType.SERVER) {
|
if (futureCollision.isTrue() && playerType != PlayerType.SERVER) {
|
||||||
if (motionResponse.y != entityMotion.y) {
|
if (motionResponse.y != entityMotion.y) {
|
||||||
|
@ -216,15 +193,6 @@ public class ContraptionCollider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3d contactPointMotion = Vec3d.ZERO;
|
|
||||||
if (surfaceCollision.isTrue()) {
|
|
||||||
entity.fallDistance = 0;
|
|
||||||
entity.onGround = true;
|
|
||||||
contraptionEntity.collidingEntities.add(entity);
|
|
||||||
if (playerType != PlayerType.SERVER)
|
|
||||||
contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hardCollision) {
|
if (hardCollision) {
|
||||||
double motionX = entityMotion.getX();
|
double motionX = entityMotion.getX();
|
||||||
double motionY = entityMotion.getY();
|
double motionY = entityMotion.getY();
|
||||||
|
@ -250,13 +218,30 @@ public class ContraptionCollider {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// totalResponse = totalResponse.add(contactPointMotion);
|
||||||
totalResponse = totalResponse.add(contactPointMotion);
|
|
||||||
Vec3d allowedMovement = getAllowedMovement(totalResponse, entity);
|
Vec3d allowedMovement = getAllowedMovement(totalResponse, entity);
|
||||||
contraptionEntity.collidingEntities.add(entity);
|
contraptionEntity.collidingEntities.add(entity);
|
||||||
entity.velocityChanged = true;
|
entity.velocityChanged = true;
|
||||||
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y,
|
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y,
|
||||||
entityPosition.z + allowedMovement.z);
|
entityPosition.z + allowedMovement.z);
|
||||||
|
entityPosition = entity.getPositionVec();
|
||||||
|
|
||||||
|
Vec3d contactPointMotion = Vec3d.ZERO;
|
||||||
|
if (surfaceCollision.isTrue()) {
|
||||||
|
entity.fallDistance = 0;
|
||||||
|
entity.onGround = true;
|
||||||
|
contraptionEntity.collidingEntities.add(entity);
|
||||||
|
if (entity instanceof ItemEntity)
|
||||||
|
entityMotion = entityMotion.mul(.5f, 1, .5f);
|
||||||
|
|
||||||
|
if (playerType != PlayerType.SERVER) {
|
||||||
|
contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition);
|
||||||
|
allowedMovement = getAllowedMovement(contactPointMotion, entity);
|
||||||
|
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y,
|
||||||
|
entityPosition.z + allowedMovement.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
entity.setMotion(entityMotion);
|
entity.setMotion(entityMotion);
|
||||||
|
|
||||||
if (playerType != PlayerType.CLIENT)
|
if (playerType != PlayerType.CLIENT)
|
||||||
|
@ -342,10 +327,12 @@ public class ContraptionCollider {
|
||||||
BlockPos max = new BlockPos(blockScanBB.maxX, blockScanBB.maxY, blockScanBB.maxZ);
|
BlockPos max = new BlockPos(blockScanBB.maxX, blockScanBB.maxY, blockScanBB.maxZ);
|
||||||
|
|
||||||
ReuseableStream<VoxelShape> potentialHits = new ReuseableStream<>(BlockPos.getAllInBox(min, max)
|
ReuseableStream<VoxelShape> potentialHits = new ReuseableStream<>(BlockPos.getAllInBox(min, max)
|
||||||
.filter(contraption.blocks::containsKey)
|
.filter(contraption.getBlocks()::containsKey)
|
||||||
.map(p -> {
|
.map(p -> {
|
||||||
BlockState blockState = contraption.blocks.get(p).state;
|
BlockState blockState = contraption.getBlocks()
|
||||||
BlockPos pos = contraption.blocks.get(p).pos;
|
.get(p).state;
|
||||||
|
BlockPos pos = contraption.getBlocks()
|
||||||
|
.get(p).pos;
|
||||||
VoxelShape collisionShape = blockState.getCollisionShape(world, p);
|
VoxelShape collisionShape = blockState.getCollisionShape(world, p);
|
||||||
return collisionShape.withOffset(pos.getX(), pos.getY(), pos.getZ());
|
return collisionShape.withOffset(pos.getX(), pos.getY(), pos.getZ());
|
||||||
})
|
})
|
||||||
|
@ -354,13 +341,13 @@ public class ContraptionCollider {
|
||||||
return potentialHits;
|
return potentialHits;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean collideBlocks(ContraptionEntity contraptionEntity) {
|
public static boolean collideBlocks(ControlledContraptionEntity contraptionEntity) {
|
||||||
if (!contraptionEntity.collisionEnabled())
|
if (!contraptionEntity.supportsTerrainCollision())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
World world = contraptionEntity.getEntityWorld();
|
World world = contraptionEntity.getEntityWorld();
|
||||||
Vec3d motion = contraptionEntity.getMotion();
|
Vec3d motion = contraptionEntity.getMotion();
|
||||||
Contraption contraption = contraptionEntity.getContraption();
|
TranslatingContraption contraption = (TranslatingContraption) contraptionEntity.getContraption();
|
||||||
AxisAlignedBB bounds = contraptionEntity.getBoundingBox();
|
AxisAlignedBB bounds = contraptionEntity.getBoundingBox();
|
||||||
Vec3d position = contraptionEntity.getPositionVec();
|
Vec3d position = contraptionEntity.getPositionVec();
|
||||||
BlockPos gridPos = new BlockPos(position);
|
BlockPos gridPos = new BlockPos(position);
|
||||||
|
@ -381,14 +368,14 @@ public class ContraptionCollider {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Other moving Contraptions
|
// Other moving Contraptions
|
||||||
for (ContraptionEntity otherContraptionEntity : world.getEntitiesWithinAABB(ContraptionEntity.class,
|
for (ControlledContraptionEntity otherContraptionEntity : world.getEntitiesWithinAABB(
|
||||||
bounds.grow(1), e -> !e.equals(contraptionEntity))) {
|
ControlledContraptionEntity.class, bounds.grow(1), e -> !e.equals(contraptionEntity))) {
|
||||||
|
|
||||||
if (!otherContraptionEntity.collisionEnabled())
|
if (!otherContraptionEntity.supportsTerrainCollision())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Vec3d otherMotion = otherContraptionEntity.getMotion();
|
Vec3d otherMotion = otherContraptionEntity.getMotion();
|
||||||
Contraption otherContraption = otherContraptionEntity.getContraption();
|
TranslatingContraption otherContraption = (TranslatingContraption) otherContraptionEntity.getContraption();
|
||||||
AxisAlignedBB otherBounds = otherContraptionEntity.getBoundingBox();
|
AxisAlignedBB otherBounds = otherContraptionEntity.getBoundingBox();
|
||||||
Vec3d otherPosition = otherContraptionEntity.getPositionVec();
|
Vec3d otherPosition = otherContraptionEntity.getPositionVec();
|
||||||
|
|
||||||
|
@ -404,7 +391,8 @@ public class ContraptionCollider {
|
||||||
for (BlockPos colliderPos : contraption.getColliders(world, movementDirection)) {
|
for (BlockPos colliderPos : contraption.getColliders(world, movementDirection)) {
|
||||||
colliderPos = colliderPos.add(gridPos)
|
colliderPos = colliderPos.add(gridPos)
|
||||||
.subtract(new BlockPos(otherPosition));
|
.subtract(new BlockPos(otherPosition));
|
||||||
if (!otherContraption.blocks.containsKey(colliderPos))
|
if (!otherContraption.getBlocks()
|
||||||
|
.containsKey(colliderPos))
|
||||||
continue;
|
continue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -413,7 +401,7 @@ public class ContraptionCollider {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCollidingWithWorld(World world, Contraption contraption, BlockPos anchor,
|
public static boolean isCollidingWithWorld(World world, TranslatingContraption contraption, BlockPos anchor,
|
||||||
Direction movementDirection) {
|
Direction movementDirection) {
|
||||||
for (BlockPos pos : contraption.getColliders(world, movementDirection)) {
|
for (BlockPos pos : contraption.getColliders(world, movementDirection)) {
|
||||||
BlockPos colliderPos = pos.add(anchor);
|
BlockPos colliderPos = pos.add(anchor);
|
||||||
|
@ -422,11 +410,11 @@ public class ContraptionCollider {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
BlockState collidedState = world.getBlockState(colliderPos);
|
BlockState collidedState = world.getBlockState(colliderPos);
|
||||||
BlockInfo blockInfo = contraption.blocks.get(pos);
|
BlockInfo blockInfo = contraption.getBlocks()
|
||||||
|
.get(pos);
|
||||||
|
|
||||||
if (AllMovementBehaviours.hasMovementBehaviour(blockInfo.state.getBlock())) {
|
if (AllMovementBehaviours.contains(blockInfo.state.getBlock())) {
|
||||||
MovementBehaviour movementBehaviour =
|
MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state.getBlock());
|
||||||
AllMovementBehaviours.getMovementBehaviour(blockInfo.state.getBlock());
|
|
||||||
if (movementBehaviour instanceof BlockBreakingMovementBehaviour) {
|
if (movementBehaviour instanceof BlockBreakingMovementBehaviour) {
|
||||||
BlockBreakingMovementBehaviour behaviour = (BlockBreakingMovementBehaviour) movementBehaviour;
|
BlockBreakingMovementBehaviour behaviour = (BlockBreakingMovementBehaviour) movementBehaviour;
|
||||||
if (!behaviour.canBreak(world, colliderPos, collidedState)
|
if (!behaviour.canBreak(world, colliderPos, collidedState)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,102 +0,0 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement;
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
|
||||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
|
||||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
|
||||||
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
|
|
||||||
public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity> {
|
|
||||||
|
|
||||||
public ContraptionEntityRenderer(EntityRendererManager rendererManager) {
|
|
||||||
super(rendererManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceLocation getEntityTexture(ContraptionEntity arg0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(ContraptionEntity entity, float yaw, float partialTicks, MatrixStack ms,
|
|
||||||
IRenderTypeBuffer buffers, int overlay) {
|
|
||||||
if (!entity.isAlive())
|
|
||||||
return;
|
|
||||||
if (entity.getContraption() == null)
|
|
||||||
return;
|
|
||||||
if (entity.getContraption()
|
|
||||||
.getType() == AllContraptionTypes.MOUNTED && entity.getRidingEntity() == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Keep a copy of the transforms in order to determine correct lighting
|
|
||||||
MatrixStack msLocal = getLocalTransform(entity);
|
|
||||||
MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal };
|
|
||||||
|
|
||||||
float angleInitialYaw = entity.getInitialYaw();
|
|
||||||
float angleYaw = entity.getYaw(partialTicks);
|
|
||||||
float anglePitch = entity.getPitch(partialTicks);
|
|
||||||
float angleRoll = entity.getRoll(partialTicks);
|
|
||||||
|
|
||||||
ms.push();
|
|
||||||
Entity ridingEntity = entity.getRidingEntity();
|
|
||||||
if (ridingEntity != null && ridingEntity instanceof AbstractMinecartEntity) {
|
|
||||||
AbstractMinecartEntity cart = (AbstractMinecartEntity) ridingEntity;
|
|
||||||
double cartX = MathHelper.lerp(partialTicks, cart.lastTickPosX, cart.getX());
|
|
||||||
double cartY = MathHelper.lerp(partialTicks, cart.lastTickPosY, cart.getY());
|
|
||||||
double cartZ = MathHelper.lerp(partialTicks, cart.lastTickPosZ, cart.getZ());
|
|
||||||
Vec3d cartPos = cart.getPos(cartX, cartY, cartZ);
|
|
||||||
|
|
||||||
for (MatrixStack stack : matrixStacks)
|
|
||||||
stack.translate(-.5f, 0, -.5f);
|
|
||||||
|
|
||||||
if (cartPos != null) {
|
|
||||||
Vec3d cartPosFront = cart.getPosOffset(cartX, cartY, cartZ, (double) 0.3F);
|
|
||||||
Vec3d cartPosBack = cart.getPosOffset(cartX, cartY, cartZ, (double) -0.3F);
|
|
||||||
if (cartPosFront == null)
|
|
||||||
cartPosFront = cartPos;
|
|
||||||
if (cartPosBack == null)
|
|
||||||
cartPosBack = cartPos;
|
|
||||||
|
|
||||||
cartX = cartPos.x - cartX;
|
|
||||||
cartY = (cartPosFront.y + cartPosBack.y) / 2.0D - cartY;
|
|
||||||
cartZ = cartPos.z - cartZ;
|
|
||||||
|
|
||||||
for (MatrixStack stack : matrixStacks)
|
|
||||||
stack.translate(cartX, cartY, cartZ);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (MatrixStack stack : matrixStacks)
|
|
||||||
MatrixStacker.of(stack)
|
|
||||||
.nudge(entity.getEntityId())
|
|
||||||
.centre()
|
|
||||||
.rotateY(angleYaw)
|
|
||||||
.rotateZ(anglePitch)
|
|
||||||
.rotateY(angleInitialYaw)
|
|
||||||
.rotateX(angleRoll)
|
|
||||||
.unCentre();
|
|
||||||
ContraptionRenderer.render(entity.world, entity.getContraption(), ms, msLocal, buffers);
|
|
||||||
ms.pop();
|
|
||||||
|
|
||||||
super.render(entity, yaw, partialTicks, ms, buffers, overlay);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MatrixStack getLocalTransform(ContraptionEntity entity) {
|
|
||||||
double pt = Minecraft.getInstance()
|
|
||||||
.getRenderPartialTicks();
|
|
||||||
MatrixStack matrixStack = new MatrixStack();
|
|
||||||
double x = MathHelper.lerp(pt, entity.lastTickPosX, entity.getX());
|
|
||||||
double y = MathHelper.lerp(pt, entity.lastTickPosY, entity.getY());
|
|
||||||
double z = MathHelper.lerp(pt, entity.lastTickPosZ, entity.getZ());
|
|
||||||
matrixStack.translate(x, y, z);
|
|
||||||
return matrixStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -21,8 +21,8 @@ public class ContraptionHandler {
|
||||||
|
|
||||||
/* Global map of loaded contraptions */
|
/* Global map of loaded contraptions */
|
||||||
|
|
||||||
public static WorldAttached<List<WeakReference<ContraptionEntity>>> loadedContraptions;
|
public static WorldAttached<List<WeakReference<AbstractContraptionEntity>>> loadedContraptions;
|
||||||
static WorldAttached<List<ContraptionEntity>> queuedAdditions;
|
static WorldAttached<List<AbstractContraptionEntity>> queuedAdditions;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
loadedContraptions = new WorldAttached<>(ArrayList::new);
|
loadedContraptions = new WorldAttached<>(ArrayList::new);
|
||||||
|
@ -30,16 +30,16 @@ public class ContraptionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tick(World world) {
|
public static void tick(World world) {
|
||||||
List<WeakReference<ContraptionEntity>> list = loadedContraptions.get(world);
|
List<WeakReference<AbstractContraptionEntity>> list = loadedContraptions.get(world);
|
||||||
List<ContraptionEntity> queued = queuedAdditions.get(world);
|
List<AbstractContraptionEntity> queued = queuedAdditions.get(world);
|
||||||
|
|
||||||
for (ContraptionEntity contraptionEntity : queued)
|
for (AbstractContraptionEntity contraptionEntity : queued)
|
||||||
list.add(new WeakReference<>(contraptionEntity));
|
list.add(new WeakReference<>(contraptionEntity));
|
||||||
queued.clear();
|
queued.clear();
|
||||||
|
|
||||||
for (Iterator<WeakReference<ContraptionEntity>> iterator = list.iterator(); iterator.hasNext();) {
|
for (Iterator<WeakReference<AbstractContraptionEntity>> iterator = list.iterator(); iterator.hasNext();) {
|
||||||
WeakReference<ContraptionEntity> weakReference = iterator.next();
|
WeakReference<AbstractContraptionEntity> weakReference = iterator.next();
|
||||||
ContraptionEntity contraptionEntity = weakReference.get();
|
AbstractContraptionEntity contraptionEntity = weakReference.get();
|
||||||
if (contraptionEntity == null || !contraptionEntity.isAlive()) {
|
if (contraptionEntity == null || !contraptionEntity.isAlive()) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
continue;
|
continue;
|
||||||
|
@ -49,9 +49,9 @@ public class ContraptionHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addSpawnedContraptionsToCollisionList(Entity entity, World world) {
|
public static void addSpawnedContraptionsToCollisionList(Entity entity, World world) {
|
||||||
if (entity instanceof ContraptionEntity)
|
if (entity instanceof AbstractContraptionEntity)
|
||||||
queuedAdditions.get(world)
|
queuedAdditions.get(world)
|
||||||
.add((ContraptionEntity) entity);
|
.add((AbstractContraptionEntity) entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void entitiesWhoJustDismountedGetSentToTheRightLocation(LivingEntity entityLiving, World world) {
|
public static void entitiesWhoJustDismountedGetSentToTheRightLocation(LivingEntity entityLiving, World world) {
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class ContraptionHandlerClient {
|
||||||
.distanceTo(origin), reach);
|
.distanceTo(origin), reach);
|
||||||
|
|
||||||
Vec3d target = RaycastHelper.getTraceTarget(player, reach, origin);
|
Vec3d target = RaycastHelper.getTraceTarget(player, reach, origin);
|
||||||
for (ContraptionEntity contraptionEntity : mc.world.getEntitiesWithinAABB(ContraptionEntity.class,
|
for (AbstractContraptionEntity contraptionEntity : mc.world.getEntitiesWithinAABB(AbstractContraptionEntity.class,
|
||||||
new AxisAlignedBB(origin, target))) {
|
new AxisAlignedBB(origin, target))) {
|
||||||
|
|
||||||
Vec3d localOrigin = contraptionEntity.toLocalVector(origin, 1);
|
Vec3d localOrigin = contraptionEntity.toLocalVector(origin, 1);
|
||||||
|
@ -84,7 +84,7 @@ public class ContraptionHandlerClient {
|
||||||
|
|
||||||
MutableObject<BlockRayTraceResult> mutableResult = new MutableObject<>();
|
MutableObject<BlockRayTraceResult> mutableResult = new MutableObject<>();
|
||||||
PredicateTraceResult predicateResult = RaycastHelper.rayTraceUntil(localOrigin, localTarget, p -> {
|
PredicateTraceResult predicateResult = RaycastHelper.rayTraceUntil(localOrigin, localTarget, p -> {
|
||||||
BlockInfo blockInfo = contraption.blocks.get(p);
|
BlockInfo blockInfo = contraption.getBlocks().get(p);
|
||||||
if (blockInfo == null)
|
if (blockInfo == null)
|
||||||
return false;
|
return false;
|
||||||
BlockState state = blockInfo.state;
|
BlockState state = blockInfo.state;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import com.simibubi.create.AllMovementBehaviours;
|
||||||
import com.simibubi.create.CreateClient;
|
import com.simibubi.create.CreateClient;
|
||||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||||
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||||
|
@ -70,7 +71,7 @@ public class ContraptionRenderer {
|
||||||
|
|
||||||
private static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
|
private static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal,
|
||||||
IRenderTypeBuffer buffer) {
|
IRenderTypeBuffer buffer) {
|
||||||
TileEntityRenderHelper.renderTileEntities(world, c.customRenderTEs, ms, msLocal, buffer);
|
TileEntityRenderHelper.renderTileEntities(world, c.renderedTileEntities, ms, msLocal, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) {
|
private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) {
|
||||||
|
@ -86,10 +87,9 @@ public class ContraptionRenderer {
|
||||||
BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize());
|
BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize());
|
||||||
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
||||||
|
|
||||||
for (BlockInfo info : c.blocks.values())
|
for (BlockInfo info : c.getBlocks().values())
|
||||||
renderWorld.setBlockState(info.pos, info.state);
|
renderWorld.setBlockState(info.pos, info.state);
|
||||||
for (BlockPos pos : c.renderOrder) {
|
for (BlockInfo info : c.getBlocks().values()) {
|
||||||
BlockInfo info = c.blocks.get(pos);
|
|
||||||
BlockState state = info.state;
|
BlockState state = info.state;
|
||||||
|
|
||||||
if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED)
|
if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED)
|
||||||
|
@ -126,7 +126,7 @@ public class ContraptionRenderer {
|
||||||
.translate(blockInfo.pos);
|
.translate(blockInfo.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
MovementBehaviour movementBehaviour = Contraption.getMovement(blockInfo.state);
|
MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state);
|
||||||
if (movementBehaviour != null)
|
if (movementBehaviour != null)
|
||||||
movementBehaviour.renderInContraption(context, ms, msLocal, buffer);
|
movementBehaviour.renderInContraption(context, ms, msLocal, buffer);
|
||||||
|
|
||||||
|
|
|
@ -15,18 +15,14 @@ public class ContraptionStallPacket extends SimplePacketBase {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
float z;
|
float z;
|
||||||
float yaw;
|
float angle;
|
||||||
float pitch;
|
|
||||||
float roll;
|
|
||||||
|
|
||||||
public ContraptionStallPacket(int entityID, double posX, double posY, double posZ, float yaw, float pitch, float roll) {
|
public ContraptionStallPacket(int entityID, double posX, double posY, double posZ, float angle) {
|
||||||
this.entityID = entityID;
|
this.entityID = entityID;
|
||||||
this.x = (float) posX;
|
this.x = (float) posX;
|
||||||
this.y = (float) posY;
|
this.y = (float) posY;
|
||||||
this.z = (float) posZ;
|
this.z = (float) posZ;
|
||||||
this.yaw = yaw;
|
this.angle = angle;
|
||||||
this.pitch = pitch;
|
|
||||||
this.roll = roll;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContraptionStallPacket(PacketBuffer buffer) {
|
public ContraptionStallPacket(PacketBuffer buffer) {
|
||||||
|
@ -34,21 +30,19 @@ public class ContraptionStallPacket extends SimplePacketBase {
|
||||||
x = buffer.readFloat();
|
x = buffer.readFloat();
|
||||||
y = buffer.readFloat();
|
y = buffer.readFloat();
|
||||||
z = buffer.readFloat();
|
z = buffer.readFloat();
|
||||||
yaw = buffer.readFloat();
|
angle = buffer.readFloat();
|
||||||
pitch = buffer.readFloat();
|
|
||||||
roll = buffer.readFloat();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(PacketBuffer buffer) {
|
public void write(PacketBuffer buffer) {
|
||||||
buffer.writeInt(entityID);
|
buffer.writeInt(entityID);
|
||||||
writeAll(buffer, x, y, z, yaw, pitch, roll);
|
writeAll(buffer, x, y, z, angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(Supplier<Context> context) {
|
public void handle(Supplier<Context> context) {
|
||||||
context.get().enqueueWork(
|
context.get().enqueueWork(
|
||||||
() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ContraptionEntity.handleStallPacket(this)));
|
() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> AbstractContraptionEntity.handleStallPacket(this)));
|
||||||
context.get().setPacketHandled(true);
|
context.get().setPacketHandled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,221 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
import static com.simibubi.create.foundation.utility.AngleHelper.angleLerp;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllEntityTypes;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingContraption;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
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.World;
|
||||||
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ex: Pistons, bearings <br>
|
||||||
|
* Controlled Contraption Entities can rotate around one axis and translate.
|
||||||
|
* <br>
|
||||||
|
* They are bound to an {@link IControlContraption}
|
||||||
|
*/
|
||||||
|
public class ControlledContraptionEntity extends AbstractContraptionEntity {
|
||||||
|
|
||||||
|
protected BlockPos controllerPos;
|
||||||
|
protected Axis rotationAxis;
|
||||||
|
protected float prevAngle;
|
||||||
|
protected float angle;
|
||||||
|
|
||||||
|
public ControlledContraptionEntity(EntityType<?> type, World world) {
|
||||||
|
super(type, world);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ControlledContraptionEntity create(World world, IControlContraption controller,
|
||||||
|
Contraption contraption) {
|
||||||
|
ControlledContraptionEntity entity =
|
||||||
|
new ControlledContraptionEntity(AllEntityTypes.CONTROLLED_CONTRAPTION.get(), world);
|
||||||
|
entity.controllerPos = controller.getBlockPosition();
|
||||||
|
entity.setContraption(contraption);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supportsTerrainCollision() {
|
||||||
|
return contraption instanceof TranslatingContraption;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setContraption(Contraption contraption) {
|
||||||
|
super.setContraption(contraption);
|
||||||
|
if (contraption instanceof BearingContraption)
|
||||||
|
rotationAxis = ((BearingContraption) contraption).getFacing()
|
||||||
|
.getAxis();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void readAdditional(CompoundNBT compound) {
|
||||||
|
super.readAdditional(compound);
|
||||||
|
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
|
||||||
|
if (compound.contains("Axis"))
|
||||||
|
rotationAxis = NBTHelper.readEnum(compound, "Axis", Axis.class);
|
||||||
|
angle = compound.getFloat("Angle");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeAdditional(CompoundNBT compound) {
|
||||||
|
super.writeAdditional(compound);
|
||||||
|
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
|
||||||
|
if (rotationAxis != null)
|
||||||
|
NBTHelper.writeEnum(compound, "Axis", rotationAxis);
|
||||||
|
compound.putFloat("Angle", angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContraptionRotationState getRotationState() {
|
||||||
|
ContraptionRotationState crs = new ContraptionRotationState();
|
||||||
|
if (rotationAxis == Axis.X)
|
||||||
|
crs.xRotation = angle;
|
||||||
|
if (rotationAxis == Axis.Y)
|
||||||
|
crs.yRotation = angle;
|
||||||
|
if (rotationAxis == Axis.Z)
|
||||||
|
crs.zRotation = angle;
|
||||||
|
return crs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3d applyRotation(Vec3d localPos, float partialTicks) {
|
||||||
|
localPos = VecHelper.rotate(localPos, getAngle(partialTicks), rotationAxis);
|
||||||
|
return localPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3d reverseRotation(Vec3d localPos, float partialTicks) {
|
||||||
|
localPos = VecHelper.rotate(localPos, -getAngle(partialTicks), rotationAxis);
|
||||||
|
return localPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAngle(float angle) {
|
||||||
|
this.angle = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getAngle(float partialTicks) {
|
||||||
|
return partialTicks == 1.0F ? angle : angleLerp(partialTicks, prevAngle, angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRotationAxis(Axis rotationAxis) {
|
||||||
|
this.rotationAxis = rotationAxis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Axis getRotationAxis() {
|
||||||
|
return rotationAxis;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPositionAndUpdate(double p_70634_1_, double p_70634_3_, double p_70634_5_) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void setPositionAndRotationDirect(double x, double y, double z, float yw, float pt, int inc, boolean t) {}
|
||||||
|
|
||||||
|
protected void tickContraption() {
|
||||||
|
prevAngle = angle;
|
||||||
|
tickActors();
|
||||||
|
|
||||||
|
if (controllerPos == null)
|
||||||
|
return;
|
||||||
|
if (!world.isBlockPresent(controllerPos))
|
||||||
|
return;
|
||||||
|
IControlContraption controller = getController();
|
||||||
|
if (controller == null) {
|
||||||
|
remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!controller.isAttachedTo(this)) {
|
||||||
|
controller.attach(this);
|
||||||
|
if (world.isRemote)
|
||||||
|
setPosition(getX(), getY(), getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3d motion = getMotion();
|
||||||
|
if (motion.length() < 1 / 4098f)
|
||||||
|
setMotion(Vec3d.ZERO);
|
||||||
|
move(motion.x, motion.y, motion.z);
|
||||||
|
if (ContraptionCollider.collideBlocks(this))
|
||||||
|
getController().collided();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean shouldActorTrigger(MovementContext context, BlockInfo blockInfo, MovementBehaviour actor,
|
||||||
|
Vec3d actorPosition, BlockPos gridPosition) {
|
||||||
|
if (super.shouldActorTrigger(context, blockInfo, actor, actorPosition, gridPosition))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Special activation timer for actors in the center of a bearing contraption
|
||||||
|
if (!(contraption instanceof BearingContraption))
|
||||||
|
return false;
|
||||||
|
BearingContraption bc = (BearingContraption) contraption;
|
||||||
|
Direction facing = bc.getFacing();
|
||||||
|
Vec3d activeAreaOffset = actor.getActiveAreaOffset(context);
|
||||||
|
if (!activeAreaOffset.mul(VecHelper.axisAlingedPlaneOf(new Vec3d(facing.getDirectionVec())))
|
||||||
|
.equals(Vec3d.ZERO))
|
||||||
|
return false;
|
||||||
|
if (!VecHelper.onSameAxis(blockInfo.pos, BlockPos.ZERO, facing.getAxis()))
|
||||||
|
return false;
|
||||||
|
context.motion = new Vec3d(facing.getDirectionVec()).scale(angle - prevAngle);
|
||||||
|
context.relativeMotion = context.motion;
|
||||||
|
int timer = context.data.getInt("StationaryTimer");
|
||||||
|
if (timer > 0) {
|
||||||
|
context.data.putInt("StationaryTimer", timer - 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.data.putInt("StationaryTimer", 20);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IControlContraption getController() {
|
||||||
|
if (controllerPos == null)
|
||||||
|
return null;
|
||||||
|
if (!world.isBlockPresent(controllerPos))
|
||||||
|
return null;
|
||||||
|
TileEntity te = world.getTileEntity(controllerPos);
|
||||||
|
if (!(te instanceof IControlContraption))
|
||||||
|
return null;
|
||||||
|
return (IControlContraption) te;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected StructureTransform makeStructureTransform() {
|
||||||
|
BlockPos offset = new BlockPos(getAnchorVec().add(.5, .5, .5));
|
||||||
|
float xRot = rotationAxis == Axis.X ? angle : 0;
|
||||||
|
float yRot = rotationAxis == Axis.Y ? angle : 0;
|
||||||
|
float zRot = rotationAxis == Axis.Z ? angle : 0;
|
||||||
|
return new StructureTransform(offset, xRot, yRot, zRot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onContraptionStalled() {
|
||||||
|
IControlContraption controller = getController();
|
||||||
|
if (controller != null)
|
||||||
|
controller.onStall();
|
||||||
|
super.onContraptionStalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float getStalledAngle() {
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleStallInformation(float x, float y, float z, float angle) {
|
||||||
|
setPos(x, y, z);
|
||||||
|
this.angle = angle;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
|
||||||
|
public class ControlledContraptionEntityRenderer extends AbstractContraptionEntityRenderer<ControlledContraptionEntity> {
|
||||||
|
|
||||||
|
public ControlledContraptionEntityRenderer(EntityRendererManager p_i46179_1_) {
|
||||||
|
super(p_i46179_1_);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void transform(ControlledContraptionEntity entity, float partialTicks,
|
||||||
|
MatrixStack[] matrixStacks) {
|
||||||
|
float angle = entity.getAngle(partialTicks);
|
||||||
|
Axis axis = entity.getRotationAxis();
|
||||||
|
|
||||||
|
for (MatrixStack stack : matrixStacks)
|
||||||
|
MatrixStacker.of(stack)
|
||||||
|
.nudge(entity.getEntityId())
|
||||||
|
.centre()
|
||||||
|
.rotate(angle, axis)
|
||||||
|
.unCentre();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,16 +4,22 @@ import com.simibubi.create.foundation.gui.AllIcons;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions;
|
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
public interface IControlContraption {
|
public interface IControlContraption {
|
||||||
|
|
||||||
public boolean isAttachedTo(ContraptionEntity contraption);
|
public boolean isAttachedTo(AbstractContraptionEntity contraption);
|
||||||
|
|
||||||
public void attach(ContraptionEntity contraption);
|
public void attach(ControlledContraptionEntity contraption);
|
||||||
|
|
||||||
public void onStall();
|
public void onStall();
|
||||||
|
|
||||||
public boolean isValid();
|
public boolean isValid();
|
||||||
|
|
||||||
|
public void collided();
|
||||||
|
|
||||||
|
public BlockPos getBlockPosition();
|
||||||
|
|
||||||
static enum MovementMode implements INamedIconOptions {
|
static enum MovementMode implements INamedIconOptions {
|
||||||
|
|
||||||
MOVE_PLACE(AllIcons.I_MOVE_PLACE),
|
MOVE_PLACE(AllIcons.I_MOVE_PLACE),
|
||||||
|
@ -70,6 +76,4 @@ public interface IControlContraption {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collided();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
public class MountedFluidStorage {
|
||||||
|
|
||||||
|
}
|
|
@ -20,7 +20,6 @@ import net.minecraftforge.items.IItemHandler;
|
||||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||||
import net.minecraftforge.items.ItemStackHandler;
|
import net.minecraftforge.items.ItemStackHandler;
|
||||||
|
|
||||||
//FIXME: More dynamic mounted storage in .4
|
|
||||||
public class MountedStorage {
|
public class MountedStorage {
|
||||||
|
|
||||||
private static final ItemStackHandler dummyHandler = new ItemStackHandler();
|
private static final ItemStackHandler dummyHandler = new ItemStackHandler();
|
||||||
|
|
|
@ -29,10 +29,11 @@ public class MovementContext {
|
||||||
public Contraption contraption;
|
public Contraption contraption;
|
||||||
public Object temporaryData;
|
public Object temporaryData;
|
||||||
|
|
||||||
public MovementContext(World world, BlockInfo info) {
|
public MovementContext(World world, BlockInfo info, Contraption contraption) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.state = info.state;
|
this.state = info.state;
|
||||||
this.tileData = info.nbt;
|
this.tileData = info.nbt;
|
||||||
|
this.contraption = contraption;
|
||||||
localPos = info.pos;
|
localPos = info.pos;
|
||||||
|
|
||||||
firstMovement = true;
|
firstMovement = true;
|
||||||
|
@ -54,8 +55,8 @@ public class MovementContext {
|
||||||
return (((int) (length * modifier + 100 * Math.signum(length))) / 100) * 100;
|
return (((int) (length * modifier + 100 * Math.signum(length))) / 100) * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MovementContext readNBT(World world, BlockInfo info, CompoundNBT nbt) {
|
public static MovementContext readNBT(World world, BlockInfo info, CompoundNBT nbt, Contraption contraption) {
|
||||||
MovementContext context = new MovementContext(world, info);
|
MovementContext context = new MovementContext(world, info, contraption);
|
||||||
context.motion = VecHelper.readNBT(nbt.getList("Motion", NBT.TAG_DOUBLE));
|
context.motion = VecHelper.readNBT(nbt.getList("Motion", NBT.TAG_DOUBLE));
|
||||||
context.relativeMotion = VecHelper.readNBT(nbt.getList("RelativeMotion", NBT.TAG_DOUBLE));
|
context.relativeMotion = VecHelper.readNBT(nbt.getList("RelativeMotion", NBT.TAG_DOUBLE));
|
||||||
if (nbt.contains("Position"))
|
if (nbt.contains("Position"))
|
||||||
|
|
|
@ -0,0 +1,493 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
import static com.simibubi.create.foundation.utility.AngleHelper.angleLerp;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllEntityTypes;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedContraption;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController;
|
||||||
|
import com.simibubi.create.foundation.entity.CreateDataSerializers;
|
||||||
|
import com.simibubi.create.foundation.item.ItemHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
|
import net.minecraft.entity.item.minecart.FurnaceMinecartEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.item.crafting.Ingredient;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.ListNBT;
|
||||||
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
import net.minecraft.network.datasync.DataParameter;
|
||||||
|
import net.minecraft.network.datasync.DataSerializers;
|
||||||
|
import net.minecraft.network.datasync.EntityDataManager;
|
||||||
|
import net.minecraft.tags.BlockTags;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ex: Minecarts, Couplings <br>
|
||||||
|
* Oriented Contraption Entities can rotate freely around two axes
|
||||||
|
* simultaneously.
|
||||||
|
*/
|
||||||
|
public class OrientedContraptionEntity extends AbstractContraptionEntity {
|
||||||
|
|
||||||
|
private static final Ingredient FUEL_ITEMS = Ingredient.fromItems(Items.COAL, Items.CHARCOAL);
|
||||||
|
|
||||||
|
private static final DataParameter<Optional<UUID>> COUPLING =
|
||||||
|
EntityDataManager.createKey(OrientedContraptionEntity.class, DataSerializers.OPTIONAL_UNIQUE_ID);
|
||||||
|
private static final DataParameter<Optional<Direction>> INITIAL_ORIENTATION =
|
||||||
|
EntityDataManager.createKey(OrientedContraptionEntity.class, CreateDataSerializers.OPTIONAL_DIRECTION);
|
||||||
|
|
||||||
|
protected Vec3d motionBeforeStall;
|
||||||
|
protected boolean forceAngle;
|
||||||
|
private boolean isSerializingFurnaceCart;
|
||||||
|
private boolean attachedExtraInventories;
|
||||||
|
|
||||||
|
public float prevYaw;
|
||||||
|
public float yaw;
|
||||||
|
public float targetYaw;
|
||||||
|
|
||||||
|
public float prevPitch;
|
||||||
|
public float pitch;
|
||||||
|
public float targetPitch;
|
||||||
|
|
||||||
|
// When placed using a contraption item
|
||||||
|
private float initialYawOffset;
|
||||||
|
|
||||||
|
public OrientedContraptionEntity(EntityType<?> type, World world) {
|
||||||
|
super(type, world);
|
||||||
|
motionBeforeStall = Vec3d.ZERO;
|
||||||
|
attachedExtraInventories = false;
|
||||||
|
isSerializingFurnaceCart = false;
|
||||||
|
initialYawOffset = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OrientedContraptionEntity create(World world, Contraption contraption,
|
||||||
|
Optional<Direction> initialOrientation) {
|
||||||
|
OrientedContraptionEntity entity =
|
||||||
|
new OrientedContraptionEntity(AllEntityTypes.ORIENTED_CONTRAPTION.get(), world);
|
||||||
|
entity.setContraption(contraption);
|
||||||
|
initialOrientation.ifPresent(entity::setInitialOrientation);
|
||||||
|
entity.startAtInitialYaw();
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInitialOrientation(Direction direction) {
|
||||||
|
dataManager.set(INITIAL_ORIENTATION, Optional.of(direction));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Direction> getInitialOrientation() {
|
||||||
|
return dataManager.get(INITIAL_ORIENTATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deferOrientation(Direction newInitialAngle) {
|
||||||
|
dataManager.set(INITIAL_ORIENTATION, Optional.empty());
|
||||||
|
yaw = initialYawOffset = newInitialAngle.getHorizontalAngle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getYawOffset() {
|
||||||
|
return getInitialYaw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getInitialYaw() {
|
||||||
|
return dataManager.get(INITIAL_ORIENTATION)
|
||||||
|
.orElse(Direction.SOUTH)
|
||||||
|
.getHorizontalAngle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerData() {
|
||||||
|
super.registerData();
|
||||||
|
dataManager.register(COUPLING, Optional.empty());
|
||||||
|
dataManager.register(INITIAL_ORIENTATION, Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContraptionRotationState getRotationState() {
|
||||||
|
ContraptionRotationState crs = new ContraptionRotationState();
|
||||||
|
|
||||||
|
float yawOffset = getYawOffset();
|
||||||
|
crs.zRotation = pitch;
|
||||||
|
crs.yRotation = -yaw + yawOffset;
|
||||||
|
|
||||||
|
if (pitch != 0 && yaw != 0) {
|
||||||
|
crs.secondYRotation = -yaw;
|
||||||
|
crs.yRotation = yawOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return crs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopRiding() {
|
||||||
|
if (!world.isRemote && isAlive())
|
||||||
|
disassemble();
|
||||||
|
super.stopRiding();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void readAdditional(CompoundNBT compound) {
|
||||||
|
super.readAdditional(compound);
|
||||||
|
|
||||||
|
if (compound.contains("InitialOrientation"))
|
||||||
|
setInitialOrientation(NBTHelper.readEnum(compound, "InitialOrientation", Direction.class));
|
||||||
|
if (compound.contains("ForceYaw"))
|
||||||
|
startAtYaw(compound.getFloat("ForceYaw"));
|
||||||
|
|
||||||
|
ListNBT vecNBT = compound.getList("CachedMotion", 6);
|
||||||
|
if (!vecNBT.isEmpty()) {
|
||||||
|
motionBeforeStall = new Vec3d(vecNBT.getDouble(0), vecNBT.getDouble(1), vecNBT.getDouble(2));
|
||||||
|
if (!motionBeforeStall.equals(Vec3d.ZERO))
|
||||||
|
targetYaw = prevYaw = yaw += yawFromVector(motionBeforeStall);
|
||||||
|
setMotion(Vec3d.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
yaw = compound.getFloat("Yaw");
|
||||||
|
pitch = compound.getFloat("Pitch");
|
||||||
|
|
||||||
|
setCouplingId(
|
||||||
|
compound.contains("OnCoupling") ? NBTUtil.readUniqueId(compound.getCompound("OnCoupling")) : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeAdditional(CompoundNBT compound) {
|
||||||
|
super.writeAdditional(compound);
|
||||||
|
|
||||||
|
if (motionBeforeStall != null)
|
||||||
|
compound.put("CachedMotion",
|
||||||
|
newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z));
|
||||||
|
|
||||||
|
Optional<Direction> optional = dataManager.get(INITIAL_ORIENTATION);
|
||||||
|
if (optional.isPresent())
|
||||||
|
NBTHelper.writeEnum(compound, "InitialOrientation", optional.get());
|
||||||
|
if (forceAngle) {
|
||||||
|
compound.putFloat("ForceYaw", yaw);
|
||||||
|
forceAngle = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
compound.putFloat("Yaw", yaw);
|
||||||
|
compound.putFloat("Pitch", pitch);
|
||||||
|
|
||||||
|
if (getCouplingId() != null)
|
||||||
|
compound.put("OnCoupling", NBTUtil.writeUniqueId(getCouplingId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyDataManagerChange(DataParameter<?> key) {
|
||||||
|
super.notifyDataManagerChange(key);
|
||||||
|
if (key == INITIAL_ORIENTATION && dataManager.get(INITIAL_ORIENTATION)
|
||||||
|
.isPresent())
|
||||||
|
startAtInitialYaw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startAtInitialYaw() {
|
||||||
|
startAtYaw(getInitialYaw());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startAtYaw(float yaw) {
|
||||||
|
targetYaw = this.yaw = prevYaw = yaw;
|
||||||
|
forceAngle = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3d applyRotation(Vec3d localPos, float partialTicks) {
|
||||||
|
localPos = VecHelper.rotate(localPos, getInitialYaw(), Axis.Y);
|
||||||
|
localPos = VecHelper.rotate(localPos, getPitch(partialTicks), Axis.Z);
|
||||||
|
localPos = VecHelper.rotate(localPos, getYaw(partialTicks), Axis.Y);
|
||||||
|
return localPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3d reverseRotation(Vec3d localPos, float partialTicks) {
|
||||||
|
localPos = VecHelper.rotate(localPos, -getYaw(partialTicks), Axis.Y);
|
||||||
|
localPos = VecHelper.rotate(localPos, -getPitch(partialTicks), Axis.Z);
|
||||||
|
localPos = VecHelper.rotate(localPos, -getInitialYaw(), Axis.Y);
|
||||||
|
return localPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getYaw(float partialTicks) {
|
||||||
|
return -(partialTicks == 1.0F ? yaw : angleLerp(partialTicks, prevYaw, yaw));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getPitch(float partialTicks) {
|
||||||
|
return partialTicks == 1.0F ? pitch : angleLerp(partialTicks, prevPitch, pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tickContraption() {
|
||||||
|
Entity e = getRidingEntity();
|
||||||
|
if (e == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
boolean rotationLock = false;
|
||||||
|
boolean pauseWhileRotating = false;
|
||||||
|
boolean wasStalled = isStalled();
|
||||||
|
if (contraption instanceof MountedContraption) {
|
||||||
|
MountedContraption mountedContraption = (MountedContraption) contraption;
|
||||||
|
rotationLock = mountedContraption.rotationMode == CartMovementMode.ROTATION_LOCKED;
|
||||||
|
pauseWhileRotating = mountedContraption.rotationMode == CartMovementMode.ROTATE_PAUSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity riding = e;
|
||||||
|
while (riding.getRidingEntity() != null && !(contraption instanceof StabilizedContraption))
|
||||||
|
riding = riding.getRidingEntity();
|
||||||
|
|
||||||
|
boolean isOnCoupling = false;
|
||||||
|
UUID couplingId = getCouplingId();
|
||||||
|
isOnCoupling = couplingId != null && riding instanceof AbstractMinecartEntity;
|
||||||
|
|
||||||
|
if (!attachedExtraInventories) {
|
||||||
|
attachInventoriesFromRidingCarts(riding, isOnCoupling, couplingId);
|
||||||
|
attachedExtraInventories = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean rotating = updateOrientation(rotationLock, wasStalled, riding, isOnCoupling);
|
||||||
|
if (!rotating || !pauseWhileRotating)
|
||||||
|
tickActors();
|
||||||
|
boolean isStalled = isStalled();
|
||||||
|
|
||||||
|
LazyOptional<MinecartController> capability =
|
||||||
|
riding.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY);
|
||||||
|
if (capability.isPresent()) {
|
||||||
|
if (!world.isRemote())
|
||||||
|
capability.orElse(null)
|
||||||
|
.setStalledExternally(isStalled);
|
||||||
|
} else {
|
||||||
|
if (isStalled) {
|
||||||
|
if (!wasStalled)
|
||||||
|
motionBeforeStall = riding.getMotion();
|
||||||
|
riding.setMotion(0, 0, 0);
|
||||||
|
}
|
||||||
|
if (wasStalled && !isStalled) {
|
||||||
|
riding.setMotion(motionBeforeStall);
|
||||||
|
motionBeforeStall = Vec3d.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!isStalled()) {
|
||||||
|
if (isOnCoupling) {
|
||||||
|
Couple<MinecartController> coupledCarts = getCoupledCartsIfPresent();
|
||||||
|
if (coupledCarts == null)
|
||||||
|
return;
|
||||||
|
coupledCarts.map(MinecartController::cart)
|
||||||
|
.forEach(this::powerFurnaceCartWithFuelFromStorage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
powerFurnaceCartWithFuelFromStorage(riding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean updateOrientation(boolean rotationLock, boolean wasStalled, Entity riding, boolean isOnCoupling) {
|
||||||
|
if (isOnCoupling) {
|
||||||
|
Couple<MinecartController> coupledCarts = getCoupledCartsIfPresent();
|
||||||
|
if (coupledCarts == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Vec3d positionVec = coupledCarts.getFirst()
|
||||||
|
.cart()
|
||||||
|
.getPositionVec();
|
||||||
|
Vec3d coupledVec = coupledCarts.getSecond()
|
||||||
|
.cart()
|
||||||
|
.getPositionVec();
|
||||||
|
|
||||||
|
double diffX = positionVec.x - coupledVec.x;
|
||||||
|
double diffY = positionVec.y - coupledVec.y;
|
||||||
|
double diffZ = positionVec.z - coupledVec.z;
|
||||||
|
|
||||||
|
prevYaw = yaw;
|
||||||
|
prevPitch = pitch;
|
||||||
|
yaw = (float) (MathHelper.atan2(diffZ, diffX) * 180 / Math.PI);
|
||||||
|
pitch = (float) (Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)) * 180 / Math.PI);
|
||||||
|
|
||||||
|
if (getCouplingId().equals(riding.getUniqueID())) {
|
||||||
|
pitch *= -1;
|
||||||
|
yaw += 180;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contraption instanceof StabilizedContraption) {
|
||||||
|
if (!(riding instanceof OrientedContraptionEntity))
|
||||||
|
return false;
|
||||||
|
StabilizedContraption stabilized = (StabilizedContraption) contraption;
|
||||||
|
Direction facing = stabilized.getFacing();
|
||||||
|
if (facing.getAxis()
|
||||||
|
.isVertical())
|
||||||
|
return false;
|
||||||
|
OrientedContraptionEntity parent = (OrientedContraptionEntity) riding;
|
||||||
|
prevYaw = yaw;
|
||||||
|
yaw = -parent.getYaw(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wasStalled)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean rotating = false;
|
||||||
|
Vec3d movementVector = riding.getMotion();
|
||||||
|
|
||||||
|
if (!(riding instanceof AbstractMinecartEntity))
|
||||||
|
movementVector = getPositionVec().subtract(prevPosX, prevPosY, prevPosZ);
|
||||||
|
Vec3d motion = movementVector.normalize();
|
||||||
|
|
||||||
|
if (!dataManager.get(INITIAL_ORIENTATION)
|
||||||
|
.isPresent() && !world.isRemote) {
|
||||||
|
if (motion.length() > 0) {
|
||||||
|
Direction facingFromVector = Direction.getFacingFromVector(motion.x, motion.y, motion.z);
|
||||||
|
if (initialYawOffset != -1)
|
||||||
|
facingFromVector = Direction.fromAngle(facingFromVector.getHorizontalAngle() - initialYawOffset);
|
||||||
|
if (facingFromVector.getAxis()
|
||||||
|
.isHorizontal())
|
||||||
|
setInitialOrientation(facingFromVector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rotationLock) {
|
||||||
|
if (motion.length() > 0) {
|
||||||
|
targetYaw = yawFromVector(motion);
|
||||||
|
if (targetYaw < 0)
|
||||||
|
targetYaw += 360;
|
||||||
|
if (yaw < 0)
|
||||||
|
yaw += 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
prevYaw = yaw;
|
||||||
|
yaw = angleLerp(0.4f, yaw, targetYaw);
|
||||||
|
if (Math.abs(AngleHelper.getShortestAngleDiff(yaw, targetYaw)) < 1f)
|
||||||
|
yaw = targetYaw;
|
||||||
|
else
|
||||||
|
rotating = true;
|
||||||
|
}
|
||||||
|
return rotating;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void powerFurnaceCartWithFuelFromStorage(Entity riding) {
|
||||||
|
if (!(riding instanceof FurnaceMinecartEntity))
|
||||||
|
return;
|
||||||
|
FurnaceMinecartEntity furnaceCart = (FurnaceMinecartEntity) riding;
|
||||||
|
|
||||||
|
// Notify to not trigger serialization side-effects
|
||||||
|
isSerializingFurnaceCart = true;
|
||||||
|
CompoundNBT nbt = furnaceCart.serializeNBT();
|
||||||
|
isSerializingFurnaceCart = false;
|
||||||
|
|
||||||
|
int fuel = nbt.getInt("Fuel");
|
||||||
|
int fuelBefore = fuel;
|
||||||
|
double pushX = nbt.getDouble("PushX");
|
||||||
|
double pushZ = nbt.getDouble("PushZ");
|
||||||
|
|
||||||
|
int i = MathHelper.floor(furnaceCart.getX());
|
||||||
|
int j = MathHelper.floor(furnaceCart.getY());
|
||||||
|
int k = MathHelper.floor(furnaceCart.getZ());
|
||||||
|
if (furnaceCart.world.getBlockState(new BlockPos(i, j - 1, k))
|
||||||
|
.isIn(BlockTags.RAILS))
|
||||||
|
--j;
|
||||||
|
|
||||||
|
BlockPos blockpos = new BlockPos(i, j, k);
|
||||||
|
BlockState blockstate = this.world.getBlockState(blockpos);
|
||||||
|
if (furnaceCart.canUseRail() && blockstate.isIn(BlockTags.RAILS))
|
||||||
|
if (fuel > 1)
|
||||||
|
riding.setMotion(riding.getMotion()
|
||||||
|
.normalize()
|
||||||
|
.scale(1));
|
||||||
|
if (fuel < 5 && contraption != null) {
|
||||||
|
ItemStack coal = ItemHelper.extract(contraption.inventory, FUEL_ITEMS, 1, false);
|
||||||
|
if (!coal.isEmpty())
|
||||||
|
fuel += 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fuel != fuelBefore || pushX != 0 || pushZ != 0) {
|
||||||
|
nbt.putInt("Fuel", fuel);
|
||||||
|
nbt.putDouble("PushX", 0);
|
||||||
|
nbt.putDouble("PushZ", 0);
|
||||||
|
furnaceCart.deserializeNBT(nbt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Couple<MinecartController> getCoupledCartsIfPresent() {
|
||||||
|
UUID couplingId = getCouplingId();
|
||||||
|
if (couplingId == null)
|
||||||
|
return null;
|
||||||
|
MinecartController controller = CapabilityMinecartController.getIfPresent(world, couplingId);
|
||||||
|
if (controller == null || !controller.isPresent())
|
||||||
|
return null;
|
||||||
|
UUID coupledCart = controller.getCoupledCart(true);
|
||||||
|
MinecartController coupledController = CapabilityMinecartController.getIfPresent(world, coupledCart);
|
||||||
|
if (coupledController == null || !coupledController.isPresent())
|
||||||
|
return null;
|
||||||
|
return Couple.create(controller, coupledController);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void attachInventoriesFromRidingCarts(Entity riding, boolean isOnCoupling, UUID couplingId) {
|
||||||
|
if (isOnCoupling) {
|
||||||
|
Couple<MinecartController> coupledCarts = getCoupledCartsIfPresent();
|
||||||
|
if (coupledCarts == null)
|
||||||
|
return;
|
||||||
|
coupledCarts.map(MinecartController::cart)
|
||||||
|
.forEach(contraption::addExtraInventories);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
contraption.addExtraInventories(riding);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompoundNBT writeWithoutTypeId(CompoundNBT nbt) {
|
||||||
|
return isSerializingFurnaceCart ? nbt : super.writeWithoutTypeId(nbt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public UUID getCouplingId() {
|
||||||
|
Optional<UUID> uuid = dataManager.get(COUPLING);
|
||||||
|
return uuid == null ? null : uuid.isPresent() ? uuid.get() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCouplingId(UUID id) {
|
||||||
|
dataManager.set(COUPLING, Optional.ofNullable(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3d getAnchorVec() {
|
||||||
|
return new Vec3d(getX() - .5, getY(), getZ() - .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected StructureTransform makeStructureTransform() {
|
||||||
|
BlockPos offset = new BlockPos(getAnchorVec().add(.5, .5, .5));
|
||||||
|
return new StructureTransform(offset, 0, -yaw + getInitialYaw(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float getStalledAngle() {
|
||||||
|
return yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleStallInformation(float x, float y, float z, float angle) {
|
||||||
|
yaw = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.culling.ClippingHelperImpl;
|
||||||
|
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
public class OrientedContraptionEntityRenderer extends AbstractContraptionEntityRenderer<OrientedContraptionEntity> {
|
||||||
|
|
||||||
|
public OrientedContraptionEntityRenderer(EntityRendererManager p_i46179_1_) {
|
||||||
|
super(p_i46179_1_);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRender(OrientedContraptionEntity entity, ClippingHelperImpl p_225626_2_, double p_225626_3_,
|
||||||
|
double p_225626_5_, double p_225626_7_) {
|
||||||
|
if (!super.shouldRender(entity, p_225626_2_, p_225626_3_, p_225626_5_, p_225626_7_))
|
||||||
|
return false;
|
||||||
|
if (entity.getContraption()
|
||||||
|
.getType() == AllContraptionTypes.MOUNTED && entity.getRidingEntity() == null)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void transform(OrientedContraptionEntity entity, float partialTicks, MatrixStack[] matrixStacks) {
|
||||||
|
float angleInitialYaw = entity.getInitialYaw();
|
||||||
|
float angleYaw = entity.getYaw(partialTicks);
|
||||||
|
float anglePitch = entity.getPitch(partialTicks);
|
||||||
|
|
||||||
|
for (MatrixStack stack : matrixStacks)
|
||||||
|
stack.translate(-.5f, 0, -.5f);
|
||||||
|
|
||||||
|
Entity ridingEntity = entity.getRidingEntity();
|
||||||
|
if (ridingEntity instanceof AbstractMinecartEntity)
|
||||||
|
repositionOnCart(partialTicks, matrixStacks, ridingEntity);
|
||||||
|
if (ridingEntity instanceof AbstractContraptionEntity) {
|
||||||
|
if (ridingEntity.getRidingEntity() instanceof AbstractMinecartEntity)
|
||||||
|
repositionOnCart(partialTicks, matrixStacks, ridingEntity.getRidingEntity());
|
||||||
|
else
|
||||||
|
repositionOnContraption(entity, partialTicks, matrixStacks, ridingEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MatrixStack stack : matrixStacks)
|
||||||
|
MatrixStacker.of(stack)
|
||||||
|
.nudge(entity.getEntityId())
|
||||||
|
.centre()
|
||||||
|
.rotateY(angleYaw)
|
||||||
|
.rotateZ(anglePitch)
|
||||||
|
.rotateY(angleInitialYaw)
|
||||||
|
.unCentre();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void repositionOnContraption(OrientedContraptionEntity entity, float partialTicks,
|
||||||
|
MatrixStack[] matrixStacks, Entity ridingEntity) {
|
||||||
|
AbstractContraptionEntity parent = (AbstractContraptionEntity) ridingEntity;
|
||||||
|
Vec3d passengerPosition = parent.getPassengerPosition(entity, partialTicks);
|
||||||
|
double x = passengerPosition.x - MathHelper.lerp(partialTicks, entity.lastTickPosX, entity.getX());
|
||||||
|
double y = passengerPosition.y - MathHelper.lerp(partialTicks, entity.lastTickPosY, entity.getY());
|
||||||
|
double z = passengerPosition.z - MathHelper.lerp(partialTicks, entity.lastTickPosZ, entity.getZ());
|
||||||
|
for (MatrixStack stack : matrixStacks)
|
||||||
|
stack.translate(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minecarts do not always render at their exact location, so the contraption
|
||||||
|
// has to adjust aswell
|
||||||
|
private void repositionOnCart(float partialTicks, MatrixStack[] matrixStacks, Entity ridingEntity) {
|
||||||
|
AbstractMinecartEntity cart = (AbstractMinecartEntity) ridingEntity;
|
||||||
|
double cartX = MathHelper.lerp(partialTicks, cart.lastTickPosX, cart.getX());
|
||||||
|
double cartY = MathHelper.lerp(partialTicks, cart.lastTickPosY, cart.getY());
|
||||||
|
double cartZ = MathHelper.lerp(partialTicks, cart.lastTickPosZ, cart.getZ());
|
||||||
|
Vec3d cartPos = cart.getPos(cartX, cartY, cartZ);
|
||||||
|
|
||||||
|
if (cartPos != null) {
|
||||||
|
Vec3d cartPosFront = cart.getPosOffset(cartX, cartY, cartZ, (double) 0.3F);
|
||||||
|
Vec3d cartPosBack = cart.getPosOffset(cartX, cartY, cartZ, (double) -0.3F);
|
||||||
|
if (cartPosFront == null)
|
||||||
|
cartPosFront = cartPos;
|
||||||
|
if (cartPosBack == null)
|
||||||
|
cartPosBack = cartPos;
|
||||||
|
|
||||||
|
cartX = cartPos.x - cartX;
|
||||||
|
cartY = (cartPosFront.y + cartPosBack.y) / 2.0D - cartY;
|
||||||
|
cartZ = cartPos.z - cartZ;
|
||||||
|
|
||||||
|
for (MatrixStack stack : matrixStacks)
|
||||||
|
stack.translate(cartX, cartY, cartZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -40,19 +40,19 @@ public class StructureTransform {
|
||||||
Axis rotationAxis;
|
Axis rotationAxis;
|
||||||
BlockPos offset;
|
BlockPos offset;
|
||||||
|
|
||||||
public StructureTransform(BlockPos offset, Vec3d rotation) {
|
public StructureTransform(BlockPos offset, float xRotation, float yRotation, float zRotation) {
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
if (rotation.x != 0) {
|
if (xRotation != 0) {
|
||||||
rotationAxis = Axis.X;
|
rotationAxis = Axis.X;
|
||||||
angle = (int) (Math.round(rotation.x / 90) * 90);
|
angle = (int) (Math.round(xRotation / 90) * 90);
|
||||||
}
|
}
|
||||||
if (rotation.y != 0) {
|
if (yRotation != 0) {
|
||||||
rotationAxis = Axis.Y;
|
rotationAxis = Axis.Y;
|
||||||
angle = (int) (Math.round(rotation.y / 90) * 90);
|
angle = (int) (Math.round(yRotation / 90) * 90);
|
||||||
}
|
}
|
||||||
if (rotation.z != 0) {
|
if (zRotation != 0) {
|
||||||
rotationAxis = Axis.Z;
|
rotationAxis = Axis.Z;
|
||||||
angle = (int) (Math.round(rotation.z / 90) * 90);
|
angle = (int) (Math.round(zRotation / 90) * 90);
|
||||||
}
|
}
|
||||||
|
|
||||||
angle %= 360;
|
angle %= 360;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
|
|
||||||
|
public abstract class TranslatingContraption extends Contraption {
|
||||||
|
|
||||||
|
protected Set<BlockPos> cachedColliders;
|
||||||
|
protected Direction cachedColliderDirection;
|
||||||
|
|
||||||
|
public Set<BlockPos> getColliders(World world, Direction movementDirection) {
|
||||||
|
if (getBlocks() == null)
|
||||||
|
return null;
|
||||||
|
if (cachedColliders == null || cachedColliderDirection != movementDirection) {
|
||||||
|
cachedColliders = new HashSet<>();
|
||||||
|
cachedColliderDirection = movementDirection;
|
||||||
|
|
||||||
|
for (BlockInfo info : getBlocks().values()) {
|
||||||
|
BlockPos offsetPos = info.pos.offset(movementDirection);
|
||||||
|
if (info.state.getCollisionShape(world, offsetPos)
|
||||||
|
.isEmpty())
|
||||||
|
continue;
|
||||||
|
if (getBlocks().containsKey(offsetPos)
|
||||||
|
&& !getBlocks().get(offsetPos).state.getCollisionShape(world, offsetPos)
|
||||||
|
.isEmpty())
|
||||||
|
continue;
|
||||||
|
cachedColliders.add(info.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return cachedColliders;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canAxisBeStabilized(Axis axis) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,9 +6,11 @@ import com.simibubi.create.AllTags.AllBlockTags;
|
||||||
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.Contraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.FaceDirection;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
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.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
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;
|
||||||
|
@ -18,40 +20,52 @@ public class BearingContraption extends Contraption {
|
||||||
protected int sailBlocks;
|
protected int sailBlocks;
|
||||||
protected Direction facing;
|
protected Direction facing;
|
||||||
|
|
||||||
|
private boolean isWindmill;
|
||||||
|
|
||||||
|
public BearingContraption() {}
|
||||||
|
|
||||||
|
public BearingContraption(boolean isWindmill, Direction facing) {
|
||||||
|
this.isWindmill = isWindmill;
|
||||||
|
this.facing = facing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean assemble(World world, BlockPos pos) {
|
||||||
|
BlockPos offset = pos.offset(facing);
|
||||||
|
if (!searchMovedStructure(world, offset, null))
|
||||||
|
return false;
|
||||||
|
startMoving(world);
|
||||||
|
expandBoundsAroundAxis(facing.getAxis());
|
||||||
|
if (isWindmill && sailBlocks == 0)
|
||||||
|
return false;
|
||||||
|
if (blocks.isEmpty())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AllContraptionTypes getType() {
|
protected AllContraptionTypes getType() {
|
||||||
return AllContraptionTypes.BEARING;
|
return AllContraptionTypes.BEARING;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BearingContraption assembleBearingAt(World world, BlockPos pos, Direction direction) {
|
|
||||||
BearingContraption construct = new BearingContraption();
|
|
||||||
construct.facing = direction;
|
|
||||||
BlockPos offset = pos.offset(direction);
|
|
||||||
if (!construct.searchMovedStructure(world, offset, null))
|
|
||||||
return null;
|
|
||||||
construct.initActors(world);
|
|
||||||
construct.expandBoundsAroundAxis(direction.getAxis());
|
|
||||||
return construct;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isAnchoringBlockAt(BlockPos pos) {
|
protected boolean isAnchoringBlockAt(BlockPos pos) {
|
||||||
return pos.equals(anchor.offset(facing.getOpposite()));
|
return pos.equals(anchor.offset(facing.getOpposite()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(BlockPos pos, Pair<BlockInfo, TileEntity> capture) {
|
public void addBlock(BlockPos pos, Pair<BlockInfo, TileEntity> capture) {
|
||||||
BlockPos localPos = pos.subtract(anchor);
|
BlockPos localPos = pos.subtract(anchor);
|
||||||
if (!blocks.containsKey(localPos) && AllBlockTags.WINDMILL_SAILS.matches(capture.getKey().state))
|
if (!getBlocks().containsKey(localPos) && AllBlockTags.WINDMILL_SAILS.matches(capture.getKey().state))
|
||||||
sailBlocks++;
|
sailBlocks++;
|
||||||
super.add(pos, capture);
|
super.addBlock(pos, capture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT writeNBT() {
|
public CompoundNBT writeNBT() {
|
||||||
CompoundNBT tag = super.writeNBT();
|
CompoundNBT tag = super.writeNBT();
|
||||||
tag.putInt("Sails", sailBlocks);
|
tag.putInt("Sails", sailBlocks);
|
||||||
tag.putInt("facing", facing.getIndex());
|
tag.putInt("Facing", facing.getIndex());
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,4 +84,9 @@ public class BearingContraption extends Contraption {
|
||||||
return facing;
|
return facing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canAxisBeStabilized(Axis axis) {
|
||||||
|
return axis == facing.getAxis();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ import java.util.List;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkContraption.HandType;
|
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkContraption.HandType;
|
||||||
import com.simibubi.create.foundation.gui.AllIcons;
|
import com.simibubi.create.foundation.gui.AllIcons;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
|
@ -15,20 +16,19 @@ import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.tileentity.TileEntityType;
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
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.Direction.AxisDirection;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
|
|
||||||
public class ClockworkBearingTileEntity extends KineticTileEntity implements IBearingTileEntity {
|
public class ClockworkBearingTileEntity extends KineticTileEntity implements IBearingTileEntity {
|
||||||
|
|
||||||
protected ContraptionEntity hourHand;
|
protected ControlledContraptionEntity hourHand;
|
||||||
protected ContraptionEntity minuteHand;
|
protected ControlledContraptionEntity minuteHand;
|
||||||
protected float hourAngle;
|
protected float hourAngle;
|
||||||
protected float minuteAngle;
|
protected float minuteAngle;
|
||||||
protected float clientHourAngleDiff;
|
protected float clientHourAngleDiff;
|
||||||
|
@ -71,7 +71,9 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
|
||||||
assembleNextTick = false;
|
assembleNextTick = false;
|
||||||
if (running) {
|
if (running) {
|
||||||
boolean canDisassemble = true;
|
boolean canDisassemble = true;
|
||||||
if (speed == 0 && (canDisassemble || hourHand == null || hourHand.getContraption().blocks.isEmpty())) {
|
if (speed == 0 && (canDisassemble || hourHand == null || hourHand.getContraption()
|
||||||
|
.getBlocks()
|
||||||
|
.isEmpty())) {
|
||||||
if (hourHand != null)
|
if (hourHand != null)
|
||||||
hourHand.getContraption()
|
hourHand.getContraption()
|
||||||
.stop(world);
|
.stop(world);
|
||||||
|
@ -103,19 +105,18 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void applyRotations() {
|
protected void applyRotations() {
|
||||||
Axis axis = getBlockState().get(BlockStateProperties.FACING)
|
BlockState blockState = getBlockState();
|
||||||
.getAxis();
|
Axis axis = Axis.X;
|
||||||
Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
|
if (blockState.has(BlockStateProperties.FACING))
|
||||||
Vec3d directionVec = new Vec3d(direction.getDirectionVec());
|
axis = blockState.get(BlockStateProperties.FACING).getAxis();
|
||||||
|
|
||||||
if (hourHand != null) {
|
if (hourHand != null) {
|
||||||
Vec3d vec = new Vec3d(1, 1, 1).scale(hourAngle)
|
hourHand.setAngle(hourAngle);
|
||||||
.mul(directionVec);
|
hourHand.setRotationAxis(axis);
|
||||||
hourHand.rotateTo(vec.x, vec.y, vec.z);
|
|
||||||
}
|
}
|
||||||
if (minuteHand != null) {
|
if (minuteHand != null) {
|
||||||
Vec3d vec = new Vec3d(1, 1, 1).scale(minuteAngle)
|
minuteHand.setAngle(minuteAngle);
|
||||||
.mul(directionVec);
|
minuteHand.setRotationAxis(axis);
|
||||||
minuteHand.rotateTo(vec.x, vec.y, vec.z);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,24 +203,26 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
|
||||||
return;
|
return;
|
||||||
if (contraption.getLeft() == null)
|
if (contraption.getLeft() == null)
|
||||||
return;
|
return;
|
||||||
if (contraption.getLeft().blocks.isEmpty())
|
if (contraption.getLeft()
|
||||||
|
.getBlocks()
|
||||||
|
.isEmpty())
|
||||||
return;
|
return;
|
||||||
BlockPos anchor = pos.offset(direction);
|
BlockPos anchor = pos.offset(direction);
|
||||||
|
|
||||||
contraption.getLeft()
|
contraption.getLeft()
|
||||||
.removeBlocksFromWorld(world, BlockPos.ZERO);
|
.removeBlocksFromWorld(world, BlockPos.ZERO);
|
||||||
hourHand = ContraptionEntity.createStationary(world, contraption.getLeft())
|
hourHand = ControlledContraptionEntity.create(world, this, contraption.getLeft());
|
||||||
.controlledBy(this);
|
|
||||||
hourHand.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
|
hourHand.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
|
||||||
|
hourHand.setRotationAxis(direction.getAxis());
|
||||||
world.addEntity(hourHand);
|
world.addEntity(hourHand);
|
||||||
|
|
||||||
if (contraption.getRight() != null) {
|
if (contraption.getRight() != null) {
|
||||||
anchor = pos.offset(direction, contraption.getRight().offset + 1);
|
anchor = pos.offset(direction, contraption.getRight().offset + 1);
|
||||||
contraption.getRight()
|
contraption.getRight()
|
||||||
.removeBlocksFromWorld(world, BlockPos.ZERO);
|
.removeBlocksFromWorld(world, BlockPos.ZERO);
|
||||||
minuteHand = ContraptionEntity.createStationary(world, contraption.getRight())
|
minuteHand = ControlledContraptionEntity.create(world, this, contraption.getRight());
|
||||||
.controlledBy(this);
|
|
||||||
minuteHand.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
|
minuteHand.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
|
||||||
|
minuteHand.setRotationAxis(direction.getAxis());
|
||||||
world.addEntity(minuteHand);
|
world.addEntity(minuteHand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +254,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void attach(ContraptionEntity contraption) {
|
public void attach(ControlledContraptionEntity contraption) {
|
||||||
if (!(contraption.getContraption() instanceof ClockworkContraption))
|
if (!(contraption.getContraption() instanceof ClockworkContraption))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -339,7 +342,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
|
||||||
public void collided() {}
|
public void collided() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAttachedTo(ContraptionEntity contraption) {
|
public boolean isAttachedTo(AbstractContraptionEntity contraption) {
|
||||||
if (!(contraption.getContraption() instanceof ClockworkContraption))
|
if (!(contraption.getContraption() instanceof ClockworkContraption))
|
||||||
return false;
|
return false;
|
||||||
ClockworkContraption cc = (ClockworkContraption) contraption.getContraption();
|
ClockworkContraption cc = (ClockworkContraption) contraption.getContraption();
|
||||||
|
@ -381,4 +384,9 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockPos getBlockPosition() {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
@ -46,11 +47,12 @@ public class ClockworkContraption extends Contraption {
|
||||||
|
|
||||||
hourArm.facing = direction;
|
hourArm.facing = direction;
|
||||||
hourArm.handType = HandType.HOUR;
|
hourArm.handType = HandType.HOUR;
|
||||||
if (!hourArm.searchMovedStructure(world, pos, direction))
|
if (!hourArm.assemble(world, pos))
|
||||||
return null;
|
return null;
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
BlockPos offsetPos = BlockPos.ZERO.offset(direction, i);
|
BlockPos offsetPos = BlockPos.ZERO.offset(direction, i);
|
||||||
if (hourArm.blocks.containsKey(offsetPos))
|
if (hourArm.getBlocks()
|
||||||
|
.containsKey(offsetPos))
|
||||||
continue;
|
continue;
|
||||||
hourArmBlocks = i;
|
hourArmBlocks = i;
|
||||||
break;
|
break;
|
||||||
|
@ -61,22 +63,29 @@ public class ClockworkContraption extends Contraption {
|
||||||
minuteArm.facing = direction;
|
minuteArm.facing = direction;
|
||||||
minuteArm.handType = HandType.MINUTE;
|
minuteArm.handType = HandType.MINUTE;
|
||||||
minuteArm.offset = hourArmBlocks;
|
minuteArm.offset = hourArmBlocks;
|
||||||
minuteArm.ignoreBlocks(hourArm.blocks.keySet(), hourArm.anchor);
|
minuteArm.ignoreBlocks(hourArm.getBlocks()
|
||||||
if (!minuteArm.searchMovedStructure(world, pos, direction))
|
.keySet(), hourArm.anchor);
|
||||||
|
if (!minuteArm.assemble(world, pos))
|
||||||
return null;
|
return null;
|
||||||
if (minuteArm.blocks.isEmpty())
|
if (minuteArm.getBlocks()
|
||||||
|
.isEmpty())
|
||||||
minuteArm = null;
|
minuteArm = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
hourArm.initActors(world);
|
hourArm.startMoving(world);
|
||||||
hourArm.expandBoundsAroundAxis(direction.getAxis());
|
hourArm.expandBoundsAroundAxis(direction.getAxis());
|
||||||
if (minuteArm != null) {
|
if (minuteArm != null) {
|
||||||
minuteArm.initActors(world);
|
minuteArm.startMoving(world);
|
||||||
minuteArm.expandBoundsAroundAxis(direction.getAxis());
|
minuteArm.expandBoundsAroundAxis(direction.getAxis());
|
||||||
}
|
}
|
||||||
return Pair.of(hourArm, minuteArm);
|
return Pair.of(hourArm, minuteArm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean assemble(World world, BlockPos pos) {
|
||||||
|
return searchMovedStructure(world, pos, facing);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
|
public boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
|
||||||
return super.searchMovedStructure(world, pos.offset(direction, offset + 1), null);
|
return super.searchMovedStructure(world, pos.offset(direction, offset + 1), null);
|
||||||
|
@ -107,6 +116,11 @@ public class ClockworkContraption extends Contraption {
|
||||||
super.readNBT(world, tag);
|
super.readNBT(world, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canAxisBeStabilized(Axis axis) {
|
||||||
|
return axis == facing.getAxis();
|
||||||
|
}
|
||||||
|
|
||||||
public static enum HandType {
|
public static enum HandType {
|
||||||
HOUR, MINUTE
|
HOUR, MINUTE
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ import static net.minecraft.state.properties.BlockStateProperties.FACING;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
|
||||||
import com.simibubi.create.foundation.item.TooltipHelper;
|
import com.simibubi.create.foundation.item.TooltipHelper;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
|
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
|
||||||
|
@ -15,18 +16,16 @@ import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.tileentity.TileEntityType;
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Direction.Axis;
|
|
||||||
import net.minecraft.util.Direction.AxisDirection;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
|
|
||||||
public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity implements IBearingTileEntity {
|
public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity implements IBearingTileEntity {
|
||||||
|
|
||||||
protected ScrollOptionBehaviour<RotationMode> movementMode;
|
protected ScrollOptionBehaviour<RotationMode> movementMode;
|
||||||
protected ContraptionEntity movedContraption;
|
protected ControlledContraptionEntity movedContraption;
|
||||||
protected float angle;
|
protected float angle;
|
||||||
protected boolean running;
|
protected boolean running;
|
||||||
protected boolean assembleNextTick;
|
protected boolean assembleNextTick;
|
||||||
|
@ -108,30 +107,28 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockPos getBlockPosition() {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
public void assemble() {
|
public void assemble() {
|
||||||
if (!(world.getBlockState(pos)
|
if (!(world.getBlockState(pos)
|
||||||
.getBlock() instanceof BearingBlock))
|
.getBlock() instanceof BearingBlock))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Direction direction = getBlockState().get(FACING);
|
Direction direction = getBlockState().get(FACING);
|
||||||
|
BearingContraption contraption = new BearingContraption(isWindmill(), direction);
|
||||||
|
if (!contraption.assemble(world, pos))
|
||||||
|
return;
|
||||||
|
|
||||||
// Collect Construct
|
|
||||||
BearingContraption contraption = BearingContraption.assembleBearingAt(world, pos, direction);
|
|
||||||
if (contraption == null)
|
|
||||||
return;
|
|
||||||
if (isWindmill() && contraption.getSailBlocks() == 0)
|
|
||||||
return;
|
|
||||||
if (contraption.blocks.isEmpty())
|
|
||||||
return;
|
|
||||||
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
|
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
|
||||||
|
movedContraption = ControlledContraptionEntity.create(world, this, contraption);
|
||||||
movedContraption = ContraptionEntity.createStationary(world, contraption)
|
|
||||||
.controlledBy(this);
|
|
||||||
BlockPos anchor = pos.offset(direction);
|
BlockPos anchor = pos.offset(direction);
|
||||||
movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
|
movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
|
||||||
|
movedContraption.setRotationAxis(direction.getAxis());
|
||||||
world.addEntity(movedContraption);
|
world.addEntity(movedContraption);
|
||||||
|
|
||||||
// Run
|
|
||||||
running = true;
|
running = true;
|
||||||
angle = 0;
|
angle = 0;
|
||||||
sendData();
|
sendData();
|
||||||
|
@ -166,8 +163,9 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
if (running) {
|
if (running) {
|
||||||
boolean canDisassemble = movementMode.get() == RotationMode.ROTATE_PLACE
|
boolean canDisassemble = movementMode.get() == RotationMode.ROTATE_PLACE
|
||||||
|| (isNearInitialAngle() && movementMode.get() == RotationMode.ROTATE_PLACE_RETURNED);
|
|| (isNearInitialAngle() && movementMode.get() == RotationMode.ROTATE_PLACE_RETURNED);
|
||||||
if (speed == 0 && (canDisassemble || movedContraption == null
|
if (speed == 0 && (canDisassemble || movedContraption == null || movedContraption.getContraption()
|
||||||
|| movedContraption.getContraption().blocks.isEmpty())) {
|
.getBlocks()
|
||||||
|
.isEmpty())) {
|
||||||
if (movedContraption != null)
|
if (movedContraption != null)
|
||||||
movedContraption.getContraption()
|
movedContraption.getContraption()
|
||||||
.stop(world);
|
.stop(world);
|
||||||
|
@ -206,18 +204,17 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void applyRotation() {
|
protected void applyRotation() {
|
||||||
if (movedContraption != null) {
|
if (movedContraption == null)
|
||||||
Axis axis = getBlockState().get(FACING)
|
return;
|
||||||
.getAxis();
|
movedContraption.setAngle(angle);
|
||||||
Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
|
BlockState blockState = getBlockState();
|
||||||
Vec3d vec = new Vec3d(1, 1, 1).scale(angle)
|
if (blockState.has(BlockStateProperties.FACING))
|
||||||
.mul(new Vec3d(direction.getDirectionVec()));
|
movedContraption.setRotationAxis(blockState.get(BlockStateProperties.FACING)
|
||||||
movedContraption.rotateTo(vec.x, vec.y, vec.z);
|
.getAxis());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void attach(ContraptionEntity contraption) {
|
public void attach(ControlledContraptionEntity contraption) {
|
||||||
BlockState blockState = getBlockState();
|
BlockState blockState = getBlockState();
|
||||||
if (!(contraption.getContraption() instanceof BearingContraption))
|
if (!(contraption.getContraption() instanceof BearingContraption))
|
||||||
return;
|
return;
|
||||||
|
@ -249,7 +246,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
public void collided() {}
|
public void collided() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAttachedTo(ContraptionEntity contraption) {
|
public boolean isAttachedTo(AbstractContraptionEntity contraption) {
|
||||||
return movedContraption == contraption;
|
return movedContraption == contraption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import com.simibubi.create.AllBlockPartials;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||||
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal,
|
||||||
|
IRenderTypeBuffer buffer) {
|
||||||
|
Direction facing = context.state.get(BlockStateProperties.FACING);
|
||||||
|
AllBlockPartials top = AllBlockPartials.BEARING_TOP;
|
||||||
|
SuperByteBuffer superBuffer = top.renderOn(context.state);
|
||||||
|
float renderPartialTicks = Minecraft.getInstance()
|
||||||
|
.getRenderPartialTicks();
|
||||||
|
|
||||||
|
// rotate to match blockstate
|
||||||
|
Axis axis = facing.getAxis();
|
||||||
|
if (axis.isHorizontal())
|
||||||
|
superBuffer.rotateCentered(Direction.UP,
|
||||||
|
AngleHelper.rad(AngleHelper.horizontalAngle(facing.getOpposite())));
|
||||||
|
superBuffer.rotateCentered(Direction.EAST, AngleHelper.rad(-90 - AngleHelper.verticalAngle(facing)));
|
||||||
|
|
||||||
|
// rotate against parent
|
||||||
|
float offset = 0;
|
||||||
|
AbstractContraptionEntity entity = context.contraption.entity;
|
||||||
|
if (entity instanceof ControlledContraptionEntity) {
|
||||||
|
ControlledContraptionEntity controlledCE = (ControlledContraptionEntity) entity;
|
||||||
|
if (controlledCE.getRotationAxis() == axis)
|
||||||
|
offset = -controlledCE.getAngle(renderPartialTicks);
|
||||||
|
|
||||||
|
} else if (entity instanceof OrientedContraptionEntity) {
|
||||||
|
OrientedContraptionEntity orientedCE = (OrientedContraptionEntity) entity;
|
||||||
|
if (axis.isVertical())
|
||||||
|
offset = -orientedCE.getYaw(renderPartialTicks);
|
||||||
|
else {
|
||||||
|
Optional<Direction> initialOrientation = orientedCE.getInitialOrientation();
|
||||||
|
if (initialOrientation.isPresent() && initialOrientation.get()
|
||||||
|
.getAxis() == axis)
|
||||||
|
offset = -orientedCE.getPitch(renderPartialTicks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (offset != 0)
|
||||||
|
superBuffer.rotateCentered(Direction.UP, AngleHelper.rad(offset));
|
||||||
|
|
||||||
|
// render
|
||||||
|
superBuffer.light(msLocal.peek()
|
||||||
|
.getModel());
|
||||||
|
superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.AllContraptionTypes;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class StabilizedContraption extends Contraption {
|
||||||
|
|
||||||
|
private Direction facing;
|
||||||
|
|
||||||
|
public StabilizedContraption() {}
|
||||||
|
|
||||||
|
public StabilizedContraption(Direction facing) {
|
||||||
|
this.facing = facing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean assemble(World world, BlockPos pos) {
|
||||||
|
BlockPos offset = pos.offset(facing);
|
||||||
|
if (!searchMovedStructure(world, offset, null))
|
||||||
|
return false;
|
||||||
|
startMoving(world);
|
||||||
|
expandBoundsAroundAxis(Axis.Y);
|
||||||
|
if (blocks.isEmpty())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isAnchoringBlockAt(BlockPos pos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AllContraptionTypes getType() {
|
||||||
|
return AllContraptionTypes.STABILIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompoundNBT writeNBT() {
|
||||||
|
CompoundNBT tag = super.writeNBT();
|
||||||
|
tag.putInt("Facing", facing.getIndex());
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readNBT(World world, CompoundNBT tag) {
|
||||||
|
facing = Direction.byIndex(tag.getInt("Facing"));
|
||||||
|
super.readNBT(world, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canAxisBeStabilized(Axis axis) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Direction getFacing() {
|
||||||
|
return facing;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ import javax.annotation.Nullable;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllShapes;
|
import com.simibubi.create.AllShapes;
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode;
|
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController;
|
||||||
|
@ -225,13 +225,13 @@ public class CartAssemblerBlock extends AbstractRailBlock
|
||||||
.isCoupledThroughContraption())
|
.isCoupledThroughContraption())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MountedContraption contraption = MountedContraption.assembleMinecart(world, pos);
|
CartMovementMode mode =
|
||||||
if (contraption == null)
|
getTileEntityOptional(world, pos).map(te -> CartMovementMode.values()[te.movementMode.value])
|
||||||
return;
|
.orElse(CartMovementMode.ROTATE);
|
||||||
if (contraption.blocks.size() == 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
withTileEntityDo(world, pos, te -> contraption.rotationMode = CartMovementMode.values()[te.movementMode.value]);
|
MountedContraption contraption = new MountedContraption(mode);
|
||||||
|
if (!contraption.assemble(world, pos))
|
||||||
|
return;
|
||||||
|
|
||||||
boolean couplingFound = contraption.connectedCart != null;
|
boolean couplingFound = contraption.connectedCart != null;
|
||||||
Optional<Direction> initialOrientation = cart.getMotion()
|
Optional<Direction> initialOrientation = cart.getMotion()
|
||||||
|
@ -245,7 +245,7 @@ public class CartAssemblerBlock extends AbstractRailBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
|
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
|
||||||
contraption.initActors(world);
|
contraption.startMoving(world);
|
||||||
contraption.expandBoundsAroundAxis(Axis.Y);
|
contraption.expandBoundsAroundAxis(Axis.Y);
|
||||||
|
|
||||||
if (couplingFound) {
|
if (couplingFound) {
|
||||||
|
@ -254,7 +254,7 @@ public class CartAssemblerBlock extends AbstractRailBlock
|
||||||
initialOrientation = Optional.of(Direction.fromAngle(MathHelper.atan2(diff.z, diff.x) * 180 / Math.PI));
|
initialOrientation = Optional.of(Direction.fromAngle(MathHelper.atan2(diff.z, diff.x) * 180 / Math.PI));
|
||||||
}
|
}
|
||||||
|
|
||||||
ContraptionEntity entity = ContraptionEntity.createMounted(world, contraption, initialOrientation);
|
OrientedContraptionEntity entity = OrientedContraptionEntity.create(world, contraption, initialOrientation);
|
||||||
if (couplingFound)
|
if (couplingFound)
|
||||||
entity.setCouplingId(cart.getUniqueID());
|
entity.setCouplingId(cart.getUniqueID());
|
||||||
entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
|
entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
@ -275,9 +275,9 @@ public class CartAssemblerBlock extends AbstractRailBlock
|
||||||
return;
|
return;
|
||||||
Entity entity = cart.getPassengers()
|
Entity entity = cart.getPassengers()
|
||||||
.get(0);
|
.get(0);
|
||||||
if (!(entity instanceof ContraptionEntity))
|
if (!(entity instanceof OrientedContraptionEntity))
|
||||||
return;
|
return;
|
||||||
ContraptionEntity contraption = (ContraptionEntity) entity;
|
OrientedContraptionEntity contraption = (OrientedContraptionEntity) entity;
|
||||||
UUID couplingId = contraption.getCouplingId();
|
UUID couplingId = contraption.getCouplingId();
|
||||||
|
|
||||||
if (couplingId == null) {
|
if (couplingId == null) {
|
||||||
|
|
|
@ -6,8 +6,9 @@ import java.util.Optional;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
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.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
import net.minecraft.block.AbstractRailBlock;
|
import net.minecraft.block.AbstractRailBlock;
|
||||||
|
@ -29,7 +30,6 @@ import net.minecraft.state.properties.RailShape;
|
||||||
import net.minecraft.tags.BlockTags;
|
import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.util.ActionResultType;
|
import net.minecraft.util.ActionResultType;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Direction.Axis;
|
|
||||||
import net.minecraft.util.NonNullList;
|
import net.minecraft.util.NonNullList;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
@ -158,16 +158,14 @@ public class MinecartContraptionItem extends Item {
|
||||||
if (tag.contains("Contraption")) {
|
if (tag.contains("Contraption")) {
|
||||||
CompoundNBT contraptionTag = tag.getCompound("Contraption");
|
CompoundNBT contraptionTag = tag.getCompound("Contraption");
|
||||||
|
|
||||||
Direction initialOrientation = Direction.SOUTH;
|
Optional<Direction> intialOrientation = Optional.empty();
|
||||||
if (contraptionTag.contains("InitialOrientation"))
|
if (contraptionTag.contains("InitialOrientation"))
|
||||||
initialOrientation = NBTHelper.readEnum(contraptionTag, "InitialOrientation", Direction.class);
|
intialOrientation =
|
||||||
|
Optional.of(NBTHelper.readEnum(contraptionTag, "InitialOrientation", Direction.class));
|
||||||
|
|
||||||
Contraption mountedContraption = Contraption.fromNBT(world, contraptionTag);
|
Contraption mountedContraption = Contraption.fromNBT(world, contraptionTag);
|
||||||
ContraptionEntity contraptionEntity =
|
OrientedContraptionEntity contraptionEntity =
|
||||||
ContraptionEntity.createMounted(world, mountedContraption, Optional.of(initialOrientation));
|
OrientedContraptionEntity.create(world, mountedContraption, intialOrientation);
|
||||||
|
|
||||||
if (newFacing != null)
|
|
||||||
contraptionEntity.reOrientate(newFacing.getAxis() == Axis.X ? newFacing : newFacing.getOpposite());
|
|
||||||
|
|
||||||
contraptionEntity.startRiding(cart);
|
contraptionEntity.startRiding(cart);
|
||||||
contraptionEntity.setPosition(cart.getX(), cart.getY(), cart.getZ());
|
contraptionEntity.setPosition(cart.getX(), cart.getY(), cart.getZ());
|
||||||
|
@ -193,7 +191,7 @@ public class MinecartContraptionItem extends Item {
|
||||||
ItemStack wrench = player.getHeldItem(event.getHand());
|
ItemStack wrench = player.getHeldItem(event.getHand());
|
||||||
if (!AllItems.WRENCH.isIn(wrench))
|
if (!AllItems.WRENCH.isIn(wrench))
|
||||||
return;
|
return;
|
||||||
if (entity instanceof ContraptionEntity)
|
if (entity instanceof AbstractContraptionEntity)
|
||||||
entity = entity.getRidingEntity();
|
entity = entity.getRidingEntity();
|
||||||
if (!(entity instanceof AbstractMinecartEntity))
|
if (!(entity instanceof AbstractMinecartEntity))
|
||||||
return;
|
return;
|
||||||
|
@ -202,12 +200,12 @@ public class MinecartContraptionItem extends Item {
|
||||||
if (type != Type.RIDEABLE && type != Type.FURNACE)
|
if (type != Type.RIDEABLE && type != Type.FURNACE)
|
||||||
return;
|
return;
|
||||||
List<Entity> passengers = cart.getPassengers();
|
List<Entity> passengers = cart.getPassengers();
|
||||||
if (passengers.isEmpty() || !(passengers.get(0) instanceof ContraptionEntity))
|
if (passengers.isEmpty() || !(passengers.get(0) instanceof OrientedContraptionEntity))
|
||||||
return;
|
return;
|
||||||
ContraptionEntity contraption = (ContraptionEntity) passengers.get(0);
|
OrientedContraptionEntity contraption = (OrientedContraptionEntity) passengers.get(0);
|
||||||
|
|
||||||
if (!event.getWorld().isRemote) {
|
if (!event.getWorld().isRemote) {
|
||||||
player.inventory.placeItemBackInInventory(event.getWorld(), create(type, contraption));
|
player.inventory.placeItemBackInInventory(event.getWorld(), create(type, contraption, 0));
|
||||||
contraption.remove();
|
contraption.remove();
|
||||||
entity.remove();
|
entity.remove();
|
||||||
}
|
}
|
||||||
|
@ -216,7 +214,8 @@ public class MinecartContraptionItem extends Item {
|
||||||
event.setCanceled(true);
|
event.setCanceled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack create(Type type, ContraptionEntity entity) {
|
public static ItemStack create(Type type, OrientedContraptionEntity entity, int playerRotation) {// TODO remove
|
||||||
|
// playerRotation
|
||||||
ItemStack stack =
|
ItemStack stack =
|
||||||
(type == Type.RIDEABLE ? AllItems.MINECART_CONTRAPTION : AllItems.FURNACE_MINECART_CONTRAPTION).asStack();
|
(type == Type.RIDEABLE ? AllItems.MINECART_CONTRAPTION : AllItems.FURNACE_MINECART_CONTRAPTION).asStack();
|
||||||
CompoundNBT tag = entity.getContraption()
|
CompoundNBT tag = entity.getContraption()
|
||||||
|
@ -227,7 +226,7 @@ public class MinecartContraptionItem extends Item {
|
||||||
|
|
||||||
Optional<Direction> initialOrientation = entity.getInitialOrientation();
|
Optional<Direction> initialOrientation = entity.getInitialOrientation();
|
||||||
if (initialOrientation.isPresent())
|
if (initialOrientation.isPresent())
|
||||||
NBTHelper.writeEnum(tag, "InitialOrientation", initialOrientation.orElse(null));
|
NBTHelper.writeEnum(tag, "InitialOrientation", initialOrientation.get());
|
||||||
|
|
||||||
stack.getOrCreateTag()
|
stack.getOrCreateTag()
|
||||||
.put("Contraption", tag);
|
.put("Contraption", tag);
|
||||||
|
|
|
@ -39,7 +39,11 @@ public class MountedContraption extends Contraption {
|
||||||
public AbstractMinecartEntity connectedCart;
|
public AbstractMinecartEntity connectedCart;
|
||||||
|
|
||||||
public MountedContraption() {
|
public MountedContraption() {
|
||||||
rotationMode = CartMovementMode.ROTATE;
|
this(CartMovementMode.ROTATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MountedContraption(CartMovementMode mode) {
|
||||||
|
rotationMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -47,19 +51,22 @@ public class MountedContraption extends Contraption {
|
||||||
return AllContraptionTypes.MOUNTED;
|
return AllContraptionTypes.MOUNTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MountedContraption assembleMinecart(World world, BlockPos pos) {
|
@Override
|
||||||
|
public boolean assemble(World world, BlockPos pos) {
|
||||||
BlockState state = world.getBlockState(pos);
|
BlockState state = world.getBlockState(pos);
|
||||||
if (!state.has(RAIL_SHAPE))
|
if (!state.has(RAIL_SHAPE))
|
||||||
return null;
|
return false;
|
||||||
|
if (!searchMovedStructure(world, pos, null))
|
||||||
MountedContraption contraption = new MountedContraption();
|
return false;
|
||||||
if (!contraption.searchMovedStructure(world, pos, null))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
Axis axis = state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z;
|
Axis axis = state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z;
|
||||||
contraption.add(pos, Pair.of(new BlockInfo(pos, AllBlocks.MINECART_ANCHOR.getDefaultState()
|
addBlock(pos, Pair.of(new BlockInfo(pos, AllBlocks.MINECART_ANCHOR.getDefaultState()
|
||||||
.with(BlockStateProperties.HORIZONTAL_AXIS, axis), null), null));
|
.with(BlockStateProperties.HORIZONTAL_AXIS, axis), null), null));
|
||||||
return contraption;
|
|
||||||
|
if (blocks.size() == 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -141,6 +148,11 @@ public class MountedContraption extends Contraption {
|
||||||
return AllBlocks.MINECART_ANCHOR.has(state);
|
return AllBlocks.MINECART_ANCHOR.has(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canAxisBeStabilized(Axis axis) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addExtraInventories(Entity cart) {
|
public void addExtraInventories(Entity cart) {
|
||||||
if (!(cart instanceof IInventory))
|
if (!(cart instanceof IInventory))
|
||||||
|
|
|
@ -3,7 +3,8 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pi
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.IControlContraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.IControlContraption;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
|
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
|
||||||
|
@ -13,6 +14,7 @@ import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||||
|
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.tileentity.TileEntityType;
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
@ -21,7 +23,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
|
||||||
public float offset;
|
public float offset;
|
||||||
public boolean running;
|
public boolean running;
|
||||||
public boolean assembleNextTick;
|
public boolean assembleNextTick;
|
||||||
public ContraptionEntity movedContraption;
|
public AbstractContraptionEntity movedContraption;
|
||||||
protected boolean forceMove;
|
protected boolean forceMove;
|
||||||
protected ScrollOptionBehaviour<MovementMode> movementMode;
|
protected ScrollOptionBehaviour<MovementMode> movementMode;
|
||||||
protected boolean waitingForSpeedChange;
|
protected boolean waitingForSpeedChange;
|
||||||
|
@ -267,7 +269,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void attach(ContraptionEntity contraption) {
|
public void attach(ControlledContraptionEntity contraption) {
|
||||||
this.movedContraption = contraption;
|
this.movedContraption = contraption;
|
||||||
if (!world.isRemote) {
|
if (!world.isRemote) {
|
||||||
this.running = true;
|
this.running = true;
|
||||||
|
@ -276,8 +278,13 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAttachedTo(ContraptionEntity contraption) {
|
public boolean isAttachedTo(AbstractContraptionEntity contraption) {
|
||||||
return movedContraption == contraption;
|
return movedContraption == contraption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockPos getBlockPosition() {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pi
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.content.contraptions.base.IRotate;
|
import com.simibubi.create.content.contraptions.base.IRotate;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.DirectionalExtenderScrollOptionSlot;
|
import com.simibubi.create.content.contraptions.components.structureMovement.DirectionalExtenderScrollOptionSlot;
|
||||||
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.tileEntity.behaviour.ValueBoxTransform;
|
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
|
||||||
|
@ -49,20 +49,17 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
|
||||||
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
||||||
|
|
||||||
// Collect Construct
|
// Collect Construct
|
||||||
PistonContraption contraption = PistonContraption.movePistonAt(world, pos, direction, getMovementSpeed() < 0);
|
PistonContraption contraption = new PistonContraption(direction, getMovementSpeed() < 0);
|
||||||
|
if (!contraption.assemble(world, pos))
|
||||||
|
return;
|
||||||
|
|
||||||
Direction positive = Direction.getFacingFromAxis(AxisDirection.POSITIVE, direction.getAxis());
|
Direction positive = Direction.getFacingFromAxis(AxisDirection.POSITIVE, direction.getAxis());
|
||||||
Direction movementDirection =
|
Direction movementDirection =
|
||||||
getSpeed() > 0 ^ direction.getAxis() != Axis.Z ? positive : positive.getOpposite();
|
getSpeed() > 0 ^ direction.getAxis() != Axis.Z ? positive : positive.getOpposite();
|
||||||
|
|
||||||
if (contraption != null) {
|
BlockPos anchor = contraption.anchor.offset(direction, contraption.initialExtensionProgress);
|
||||||
BlockPos anchor = contraption.getAnchor()
|
|
||||||
.offset(direction, contraption.initialExtensionProgress);
|
|
||||||
if (ContraptionCollider.isCollidingWithWorld(world, contraption, anchor.offset(movementDirection),
|
if (ContraptionCollider.isCollidingWithWorld(world, contraption, anchor.offset(movementDirection),
|
||||||
movementDirection))
|
movementDirection))
|
||||||
contraption = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contraption == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Check if not at limit already
|
// Check if not at limit already
|
||||||
|
@ -80,8 +77,7 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
|
||||||
|
|
||||||
BlockPos startPos = BlockPos.ZERO.offset(direction, contraption.initialExtensionProgress);
|
BlockPos startPos = BlockPos.ZERO.offset(direction, contraption.initialExtensionProgress);
|
||||||
contraption.removeBlocksFromWorld(world, startPos);
|
contraption.removeBlocksFromWorld(world, startPos);
|
||||||
movedContraption = ContraptionEntity.createStationary(getWorld(), contraption)
|
movedContraption = ControlledContraptionEntity.create(getWorld(), this, contraption);
|
||||||
.controlledBy(this);
|
|
||||||
applyContraptionPosition();
|
applyContraptionPosition();
|
||||||
forceMove = true;
|
forceMove = true;
|
||||||
world.addEntity(movedContraption);
|
world.addEntity(movedContraption);
|
||||||
|
@ -147,8 +143,7 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
|
||||||
protected Vec3d toPosition(float offset) {
|
protected Vec3d toPosition(float offset) {
|
||||||
Vec3d position = new Vec3d(getBlockState().get(BlockStateProperties.FACING)
|
Vec3d position = new Vec3d(getBlockState().get(BlockStateProperties.FACING)
|
||||||
.getDirectionVec()).scale(offset);
|
.getDirectionVec()).scale(offset);
|
||||||
return position.add(new Vec3d(movedContraption.getContraption()
|
return position.add(new Vec3d(movedContraption.getContraption().anchor));
|
||||||
.getAnchor()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,16 +15,14 @@ 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.TranslatingContraption;
|
||||||
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.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.CarpetBlock;
|
import net.minecraft.block.CarpetBlock;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.nbt.ListNBT;
|
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.state.properties.PistonType;
|
import net.minecraft.state.properties.PistonType;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
@ -35,28 +33,36 @@ 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;
|
||||||
|
|
||||||
public class PistonContraption extends Contraption {
|
public class PistonContraption extends TranslatingContraption {
|
||||||
|
|
||||||
protected AxisAlignedBB pistonExtensionCollisionBox;
|
|
||||||
|
|
||||||
protected int extensionLength;
|
protected int extensionLength;
|
||||||
protected int initialExtensionProgress;
|
protected int initialExtensionProgress;
|
||||||
protected Direction orientation;
|
protected Direction orientation;
|
||||||
|
|
||||||
|
private AxisAlignedBB pistonExtensionCollisionBox;
|
||||||
|
private boolean retract;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AllContraptionTypes getType() {
|
protected AllContraptionTypes getType() {
|
||||||
return AllContraptionTypes.PISTON;
|
return AllContraptionTypes.PISTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PistonContraption movePistonAt(World world, BlockPos pos, Direction direction, boolean retract) {
|
public PistonContraption() {}
|
||||||
PistonContraption construct = new PistonContraption();
|
|
||||||
construct.orientation = direction;
|
public PistonContraption(Direction direction, boolean retract) {
|
||||||
if (!construct.collectExtensions(world, pos, direction))
|
orientation = direction;
|
||||||
return null;
|
this.retract = retract;
|
||||||
if (!construct.searchMovedStructure(world, construct.anchor, retract ? direction.getOpposite() : direction))
|
}
|
||||||
return null;
|
|
||||||
construct.initActors(world);
|
@Override
|
||||||
return construct;
|
public boolean assemble(World world, BlockPos pos) {
|
||||||
|
if (!collectExtensions(world, pos, orientation))
|
||||||
|
return false;
|
||||||
|
if (!searchMovedStructure(world, anchor, retract ? orientation.getOpposite() : orientation))
|
||||||
|
return false;
|
||||||
|
bounds = bounds.union(pistonExtensionCollisionBox);
|
||||||
|
startMoving(world);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean collectExtensions(World world, BlockPos pos, Direction direction) {
|
private boolean collectExtensions(World world, BlockPos pos, Direction direction) {
|
||||||
|
@ -123,7 +129,7 @@ public class PistonContraption extends Contraption {
|
||||||
for (BlockInfo pole : poles) {
|
for (BlockInfo pole : poles) {
|
||||||
BlockPos relPos = pole.pos.offset(direction, -extensionsInFront);
|
BlockPos relPos = pole.pos.offset(direction, -extensionsInFront);
|
||||||
BlockPos localPos = relPos.subtract(anchor);
|
BlockPos localPos = relPos.subtract(anchor);
|
||||||
blocks.put(localPos, new BlockInfo(localPos, pole.state, null));
|
getBlocks().put(localPos, new BlockInfo(localPos, pole.state, null));
|
||||||
pistonExtensionCollisionBox = pistonExtensionCollisionBox.union(new AxisAlignedBB(localPos));
|
pistonExtensionCollisionBox = pistonExtensionCollisionBox.union(new AxisAlignedBB(localPos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,8 +171,8 @@ public class PistonContraption extends Contraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(BlockPos pos, Pair<BlockInfo, TileEntity> capture) {
|
public void addBlock(BlockPos pos, Pair<BlockInfo, TileEntity> capture) {
|
||||||
super.add(pos.offset(orientation, -initialExtensionProgress), capture);
|
super.addBlock(pos.offset(orientation, -initialExtensionProgress), capture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -205,30 +211,18 @@ public class PistonContraption extends Contraption {
|
||||||
@Override
|
@Override
|
||||||
public void readNBT(World world, CompoundNBT nbt) {
|
public void readNBT(World world, CompoundNBT nbt) {
|
||||||
super.readNBT(world, nbt);
|
super.readNBT(world, nbt);
|
||||||
extensionLength = nbt.getInt("ExtensionLength");
|
|
||||||
initialExtensionProgress = nbt.getInt("InitialLength");
|
initialExtensionProgress = nbt.getInt("InitialLength");
|
||||||
|
extensionLength = nbt.getInt("ExtensionLength");
|
||||||
orientation = Direction.byIndex(nbt.getInt("Orientation"));
|
orientation = Direction.byIndex(nbt.getInt("Orientation"));
|
||||||
if (nbt.contains("BoundsBack"))
|
|
||||||
pistonExtensionCollisionBox = NBTHelper.readAABB(nbt.getList("BoundsBack", 5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT writeNBT() {
|
public CompoundNBT writeNBT() {
|
||||||
CompoundNBT nbt = super.writeNBT();
|
CompoundNBT nbt = super.writeNBT();
|
||||||
|
|
||||||
if (pistonExtensionCollisionBox != null) {
|
|
||||||
ListNBT bb = NBTHelper.writeAABB(pistonExtensionCollisionBox);
|
|
||||||
nbt.put("BoundsBack", bb);
|
|
||||||
}
|
|
||||||
nbt.putInt("InitialLength", initialExtensionProgress);
|
nbt.putInt("InitialLength", initialExtensionProgress);
|
||||||
nbt.putInt("ExtensionLength", extensionLength);
|
nbt.putInt("ExtensionLength", extensionLength);
|
||||||
nbt.putInt("Orientation", orientation.getIndex());
|
nbt.putInt("Orientation", orientation.getIndex());
|
||||||
|
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AxisAlignedBB getBoundingBox() {
|
|
||||||
return super.getBoundingBox().union(pistonExtensionCollisionBox);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement.pulley;
|
package com.simibubi.create.content.contraptions.components.structureMovement.pulley;
|
||||||
|
|
||||||
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.Contraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption;
|
||||||
|
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class PulleyContraption extends Contraption {
|
public class PulleyContraption extends TranslatingContraption {
|
||||||
|
|
||||||
int initialOffset;
|
int initialOffset;
|
||||||
|
|
||||||
|
@ -16,13 +16,18 @@ public class PulleyContraption extends Contraption {
|
||||||
return AllContraptionTypes.PULLEY;
|
return AllContraptionTypes.PULLEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PulleyContraption assemblePulleyAt(World world, BlockPos pos, int initialOffset) {
|
public PulleyContraption() {}
|
||||||
PulleyContraption construct = new PulleyContraption();
|
|
||||||
construct.initialOffset = initialOffset;
|
public PulleyContraption(int initialOffset) {
|
||||||
if (!construct.searchMovedStructure(world, pos, null))
|
this.initialOffset = initialOffset;
|
||||||
return null;
|
}
|
||||||
construct.initActors(world);
|
|
||||||
return construct;
|
@Override
|
||||||
|
public boolean assemble(World world, BlockPos pos) {
|
||||||
|
if (!searchMovedStructure(world, pos, null))
|
||||||
|
return false;
|
||||||
|
startMoving(world);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -4,7 +4,7 @@ import com.simibubi.create.AllBlockPartials;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.CreateClient;
|
import com.simibubi.create.CreateClient;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||||
|
@ -19,7 +19,8 @@ public class PulleyRenderer extends AbstractPulleyRenderer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Axis getShaftAxis(KineticTileEntity te) {
|
protected Axis getShaftAxis(KineticTileEntity te) {
|
||||||
return te.getBlockState().get(PulleyBlock.HORIZONTAL_AXIS);
|
return te.getBlockState()
|
||||||
|
.get(PulleyBlock.HORIZONTAL_AXIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -45,11 +46,10 @@ public class PulleyRenderer extends AbstractPulleyRenderer {
|
||||||
float offset = pulley.getInterpolatedOffset(moving ? partialTicks : 0.5f);
|
float offset = pulley.getInterpolatedOffset(moving ? partialTicks : 0.5f);
|
||||||
|
|
||||||
if (pulley.movedContraption != null) {
|
if (pulley.movedContraption != null) {
|
||||||
ContraptionEntity e = pulley.movedContraption;
|
AbstractContraptionEntity e = pulley.movedContraption;
|
||||||
PulleyContraption c = (PulleyContraption) pulley.movedContraption.getContraption();
|
PulleyContraption c = (PulleyContraption) pulley.movedContraption.getContraption();
|
||||||
double entityPos = MathHelper.lerp(partialTicks, e.lastTickPosY, e.getY());
|
double entityPos = MathHelper.lerp(partialTicks, e.lastTickPosY, e.getY());
|
||||||
offset = (float) -(entityPos - c.getAnchor()
|
offset = (float) -(entityPos - c.anchor.getY() - c.initialOffset);
|
||||||
.getY() - c.initialOffset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
|
|
|
@ -3,7 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pu
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
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.ContraptionCollider;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.piston.LinearActuatorTileEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.piston.LinearActuatorTileEntity;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform;
|
import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform;
|
||||||
|
@ -20,6 +20,7 @@ import net.minecraft.tileentity.TileEntityType;
|
||||||
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.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
public class PulleyTileEntity extends LinearActuatorTileEntity {
|
public class PulleyTileEntity extends LinearActuatorTileEntity {
|
||||||
|
@ -54,34 +55,36 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
|
||||||
|
|
||||||
// Collect Construct
|
// Collect Construct
|
||||||
if (!world.isRemote) {
|
if (!world.isRemote) {
|
||||||
BlockPos anchor = pos.down((int) (offset + 1));
|
BlockPos anchor = pos.down(MathHelper.floor(offset + 1));
|
||||||
initialOffset = (int) (offset);
|
initialOffset = MathHelper.floor(offset);
|
||||||
PulleyContraption contraption = PulleyContraption.assemblePulleyAt(world, anchor, (int) offset);
|
PulleyContraption contraption = new PulleyContraption(initialOffset);
|
||||||
|
boolean canAssembleStructure = contraption.assemble(world, anchor);
|
||||||
|
|
||||||
if (contraption != null) {
|
if (canAssembleStructure) {
|
||||||
Direction movementDirection = getSpeed() > 0 ? Direction.DOWN : Direction.UP;
|
Direction movementDirection = getSpeed() > 0 ? Direction.DOWN : Direction.UP;
|
||||||
if (ContraptionCollider.isCollidingWithWorld(world, contraption, anchor.offset(movementDirection),
|
if (ContraptionCollider.isCollidingWithWorld(world, contraption, anchor.offset(movementDirection),
|
||||||
movementDirection))
|
movementDirection))
|
||||||
contraption = null;
|
canAssembleStructure = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contraption == null && getSpeed() > 0)
|
if (!canAssembleStructure && getSpeed() > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = ((int) offset); i > 0; i--) {
|
for (int i = ((int) offset); i > 0; i--) {
|
||||||
BlockPos offset = pos.down(i);
|
BlockPos offset = pos.down(i);
|
||||||
BlockState oldState = world.getBlockState(offset);
|
BlockState oldState = world.getBlockState(offset);
|
||||||
if (oldState.getBlock() instanceof IWaterLoggable && oldState.has(BlockStateProperties.WATERLOGGED) && oldState.get(BlockStateProperties.WATERLOGGED)) {
|
if (oldState.getBlock() instanceof IWaterLoggable && oldState.has(BlockStateProperties.WATERLOGGED)
|
||||||
|
&& oldState.get(BlockStateProperties.WATERLOGGED)) {
|
||||||
world.setBlockState(offset, Blocks.WATER.getDefaultState(), 66);
|
world.setBlockState(offset, Blocks.WATER.getDefaultState(), 66);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
world.setBlockState(offset, Blocks.AIR.getDefaultState(), 66);
|
world.setBlockState(offset, Blocks.AIR.getDefaultState(), 66);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contraption != null && !contraption.blocks.isEmpty()) {
|
if (contraption != null && !contraption.getBlocks()
|
||||||
|
.isEmpty()) {
|
||||||
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
|
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
|
||||||
movedContraption = ContraptionEntity.createStationary(world, contraption)
|
movedContraption = ControlledContraptionEntity.create(world, this, contraption);
|
||||||
.controlledBy(this);
|
|
||||||
movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
|
movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
|
||||||
world.addEntity(movedContraption);
|
world.addEntity(movedContraption);
|
||||||
forceMove = true;
|
forceMove = true;
|
||||||
|
@ -109,7 +112,10 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
|
||||||
world.destroyBlock(magnetPos, world.getBlockState(magnetPos)
|
world.destroyBlock(magnetPos, world.getBlockState(magnetPos)
|
||||||
.getCollisionShape(world, magnetPos)
|
.getCollisionShape(world, magnetPos)
|
||||||
.isEmpty());
|
.isEmpty());
|
||||||
world.setBlockState(magnetPos, AllBlocks.PULLEY_MAGNET.getDefaultState().with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)), 66);
|
world.setBlockState(magnetPos, AllBlocks.PULLEY_MAGNET.getDefaultState()
|
||||||
|
.with(BlockStateProperties.WATERLOGGED,
|
||||||
|
Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)),
|
||||||
|
66);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean[] waterlog = new boolean[(int) offset];
|
boolean[] waterlog = new boolean[(int) offset];
|
||||||
|
@ -123,7 +129,8 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
|
||||||
.isEmpty());
|
.isEmpty());
|
||||||
}
|
}
|
||||||
for (int i = 1; i <= ((int) offset) - 1; i++)
|
for (int i = 1; i <= ((int) offset) - 1; i++)
|
||||||
world.setBlockState(pos.down(i), AllBlocks.ROPE.getDefaultState().with(BlockStateProperties.WATERLOGGED, waterlog[i]), 66);
|
world.setBlockState(pos.down(i), AllBlocks.ROPE.getDefaultState()
|
||||||
|
.with(BlockStateProperties.WATERLOGGED, waterlog[i]), 66);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (movedContraption != null)
|
if (movedContraption != null)
|
||||||
|
@ -142,7 +149,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
|
||||||
protected Vec3d toPosition(float offset) {
|
protected Vec3d toPosition(float offset) {
|
||||||
if (movedContraption.getContraption() instanceof PulleyContraption) {
|
if (movedContraption.getContraption() instanceof PulleyContraption) {
|
||||||
PulleyContraption contraption = (PulleyContraption) movedContraption.getContraption();
|
PulleyContraption contraption = (PulleyContraption) movedContraption.getContraption();
|
||||||
return new Vec3d(contraption.getAnchor()).add(0, contraption.initialOffset - offset, 0);
|
return new Vec3d(contraption.anchor).add(0, contraption.initialOffset - offset, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
return Vec3d.ZERO;
|
return Vec3d.ZERO;
|
||||||
|
|
|
@ -2,7 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.sy
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
@ -20,7 +20,7 @@ public class ContraptionInteractionPacket extends SimplePacketBase {
|
||||||
private BlockPos localPos;
|
private BlockPos localPos;
|
||||||
private Direction face;
|
private Direction face;
|
||||||
|
|
||||||
public ContraptionInteractionPacket(ContraptionEntity target, Hand hand, BlockPos localPos, Direction side) {
|
public ContraptionInteractionPacket(AbstractContraptionEntity target, Hand hand, BlockPos localPos, Direction side) {
|
||||||
this.interactionHand = hand;
|
this.interactionHand = hand;
|
||||||
this.localPos = localPos;
|
this.localPos = localPos;
|
||||||
this.target = target.getEntityId();
|
this.target = target.getEntityId();
|
||||||
|
@ -53,9 +53,9 @@ public class ContraptionInteractionPacket extends SimplePacketBase {
|
||||||
return;
|
return;
|
||||||
Entity entityByID = sender.getServerWorld()
|
Entity entityByID = sender.getServerWorld()
|
||||||
.getEntityByID(target);
|
.getEntityByID(target);
|
||||||
if (!(entityByID instanceof ContraptionEntity))
|
if (!(entityByID instanceof AbstractContraptionEntity))
|
||||||
return;
|
return;
|
||||||
ContraptionEntity contraptionEntity = (ContraptionEntity) entityByID;
|
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
|
||||||
if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand))
|
if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand))
|
||||||
sender.swingHand(interactionHand, true);
|
sender.swingHand(interactionHand, true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
@ -46,9 +46,9 @@ public class ContraptionSeatMappingPacket extends SimplePacketBase {
|
||||||
context.get()
|
context.get()
|
||||||
.enqueueWork(() -> {
|
.enqueueWork(() -> {
|
||||||
Entity entityByID = Minecraft.getInstance().world.getEntityByID(entityID);
|
Entity entityByID = Minecraft.getInstance().world.getEntityByID(entityID);
|
||||||
if (!(entityByID instanceof ContraptionEntity))
|
if (!(entityByID instanceof AbstractContraptionEntity))
|
||||||
return;
|
return;
|
||||||
ContraptionEntity contraptionEntity = (ContraptionEntity) entityByID;
|
AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID;
|
||||||
contraptionEntity.getContraption()
|
contraptionEntity.getContraption()
|
||||||
.setSeatMapping(mapping);
|
.setSeatMapping(mapping);
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
@ -38,7 +38,7 @@ public class CouplingHandler {
|
||||||
LazyOptional<MinecartController> optional = e.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY);
|
LazyOptional<MinecartController> optional = e.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY);
|
||||||
if (!optional.isPresent())
|
if (!optional.isPresent())
|
||||||
return;
|
return;
|
||||||
if (event.getEntityMounting() instanceof ContraptionEntity)
|
if (event.getEntityMounting() instanceof AbstractContraptionEntity)
|
||||||
return;
|
return;
|
||||||
MinecartController controller = optional.orElse(null);
|
MinecartController controller = optional.orElse(null);
|
||||||
if (controller.isCoupledThroughContraption()) {
|
if (controller.isCoupledThroughContraption()) {
|
||||||
|
|
|
@ -11,7 +11,8 @@ import javax.annotation.Nullable;
|
||||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
|
||||||
import com.simibubi.create.foundation.networking.AllPackets;
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
@ -131,8 +132,8 @@ public class MinecartController implements INBTSerializable<CompoundNBT> {
|
||||||
List<Entity> passengers = cart().getPassengers();
|
List<Entity> passengers = cart().getPassengers();
|
||||||
if (!passengers.isEmpty()) {
|
if (!passengers.isEmpty()) {
|
||||||
Entity entity = passengers.get(0);
|
Entity entity = passengers.get(0);
|
||||||
if (entity instanceof ContraptionEntity)
|
if (entity instanceof AbstractContraptionEntity)
|
||||||
((ContraptionEntity) entity).disassemble();
|
((AbstractContraptionEntity) entity).disassemble();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,9 +173,9 @@ public class MinecartController implements INBTSerializable<CompoundNBT> {
|
||||||
if (passengers.isEmpty())
|
if (passengers.isEmpty())
|
||||||
return;
|
return;
|
||||||
Entity entity = passengers.get(0);
|
Entity entity = passengers.get(0);
|
||||||
if (!(entity instanceof ContraptionEntity))
|
if (!(entity instanceof OrientedContraptionEntity))
|
||||||
return;
|
return;
|
||||||
ContraptionEntity contraption = (ContraptionEntity) entity;
|
OrientedContraptionEntity contraption = (OrientedContraptionEntity) entity;
|
||||||
UUID couplingId = contraption.getCouplingId();
|
UUID couplingId = contraption.getCouplingId();
|
||||||
if (couplingId == cd.mainCartID) {
|
if (couplingId == cd.mainCartID) {
|
||||||
contraption.setCouplingId(cd.connectedCartID);
|
contraption.setCouplingId(cd.connectedCartID);
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class BasinMovementBehaviour extends MovementBehaviour {
|
||||||
}
|
}
|
||||||
context.tileData.put(key, itemStackHandler.serializeNBT());
|
context.tileData.put(key, itemStackHandler.serializeNBT());
|
||||||
});
|
});
|
||||||
context.contraption.customRenderTEs.stream()
|
context.contraption.renderedTileEntities.stream()
|
||||||
.filter(te -> te.getPos()
|
.filter(te -> te.getPos()
|
||||||
.equals(context.localPos) && te instanceof BasinTileEntity)
|
.equals(context.localPos) && te instanceof BasinTileEntity)
|
||||||
.forEach(te -> ((BasinTileEntity) te).readOnlyItems(context.tileData));
|
.forEach(te -> ((BasinTileEntity) te).readOnlyItems(context.tileData));
|
||||||
|
|
|
@ -7,7 +7,7 @@ import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
|
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
|
import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
|
||||||
import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
|
import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
|
||||||
|
@ -184,7 +184,7 @@ public class BeltMovementHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shouldIgnoreBlocking(Entity me, Entity other) {
|
public static boolean shouldIgnoreBlocking(Entity me, Entity other) {
|
||||||
if (other instanceof ContraptionEntity)
|
if (other instanceof AbstractContraptionEntity)
|
||||||
return true;
|
return true;
|
||||||
if (other instanceof HangingEntity)
|
if (other instanceof HangingEntity)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.simibubi.create.foundation.block;
|
package com.simibubi.create.foundation.block;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
|
@ -23,6 +24,13 @@ public interface ITE<T extends TileEntity> {
|
||||||
} catch (TileEntityException e) {}
|
} catch (TileEntityException e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default Optional<T> getTileEntityOptional(IBlockReader world, BlockPos pos) {
|
||||||
|
try {
|
||||||
|
return Optional.of(getTileEntity(world, pos));
|
||||||
|
} catch (TileEntityException e) {}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
default T getTileEntity(IBlockReader worldIn, BlockPos pos) throws TileEntityException {
|
default T getTileEntity(IBlockReader worldIn, BlockPos pos) throws TileEntityException {
|
||||||
TileEntity tileEntity = worldIn.getTileEntity(pos);
|
TileEntity tileEntity = worldIn.getTileEntity(pos);
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.simibubi.create.foundation.entity;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraft.network.datasync.DataSerializers;
|
||||||
|
import net.minecraft.network.datasync.IDataSerializer;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
|
||||||
|
public class CreateDataSerializers {
|
||||||
|
|
||||||
|
public static final IDataSerializer<Optional<Direction>> OPTIONAL_DIRECTION =
|
||||||
|
new IDataSerializer<Optional<Direction>>() {
|
||||||
|
|
||||||
|
public void write(PacketBuffer buffer, Optional<Direction> opt) {
|
||||||
|
buffer.writeVarInt(opt.map(Direction::ordinal)
|
||||||
|
.orElse(-1) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Direction> read(PacketBuffer buffer) {
|
||||||
|
int i = buffer.readVarInt();
|
||||||
|
return i == 0 ? Optional.empty() : Optional.of(Direction.values()[i - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Direction> copyValue(Optional<Direction> opt) {
|
||||||
|
return Optional.ofNullable(opt.orElse(null));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static {
|
||||||
|
DataSerializers.registerSerializer(OPTIONAL_DIRECTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package com.simibubi.create.foundation.utility;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.Vector3f;
|
import net.minecraft.client.renderer.Vector3f;
|
||||||
|
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.util.math.Vec3d;
|
||||||
import net.minecraft.util.math.Vec3i;
|
import net.minecraft.util.math.Vec3i;
|
||||||
|
@ -21,6 +22,12 @@ public class MatrixStacker {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MatrixStacker rotate(double angle, Axis axis) {
|
||||||
|
Vector3f vec =
|
||||||
|
axis == Axis.X ? Vector3f.POSITIVE_X : axis == Axis.Y ? Vector3f.POSITIVE_Y : Vector3f.POSITIVE_Z;
|
||||||
|
return multiply(vec, angle);
|
||||||
|
}
|
||||||
|
|
||||||
public MatrixStacker rotateX(double angle) {
|
public MatrixStacker rotateX(double angle) {
|
||||||
return multiply(Vector3f.POSITIVE_X, angle);
|
return multiply(Vector3f.POSITIVE_X, angle);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue