It's alive

- Contraptions pushed by Mechanical Pistons are now wrapped into entities
- Fixed Lighting and Positioning of Contraption entities
This commit is contained in:
simibubi 2019-12-06 19:48:15 +01:00
parent 1d96f50b9a
commit 1563a3991c
15 changed files with 413 additions and 399 deletions

View file

@ -8,13 +8,11 @@ import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.TooltipHelper;
import com.simibubi.create.modules.contraptions.KineticDebugger;
import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.TurntableHandler;
import com.simibubi.create.modules.contraptions.relays.belt.BeltConnectorItemHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.api.distmarker.Dist;

View file

@ -1,12 +1,11 @@
package com.simibubi.create;
import com.simibubi.create.foundation.world.OreGeneration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.simibubi.create.foundation.world.OreGeneration;
import com.simibubi.create.modules.ModuleLoadedCondition;
import com.simibubi.create.modules.contraptions.TorquePropagator;
import com.simibubi.create.modules.contraptions.receivers.constructs.piston.MovingConstructHandler;
import com.simibubi.create.modules.logistics.FrequencyHandler;
import com.simibubi.create.modules.logistics.management.LogisticalNetworkHandler;
import com.simibubi.create.modules.logistics.transport.villager.LogisticianHandler;
@ -25,7 +24,6 @@ import net.minecraft.village.PointOfInterestType;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
@ -43,7 +41,6 @@ public class Create {
public static ItemGroup creativeTab = new CreateItemGroup();
public static ServerSchematicLoader schematicReceiver;
public static FrequencyHandler frequencyHandler;
public static MovingConstructHandler constructHandler;
public static LogisticalNetworkHandler logisticalNetworkHandler;
public static TorquePropagator torquePropagator;
public static LogisticianHandler logisticianHandler;
@ -75,7 +72,6 @@ public class Create {
public static void init(final FMLCommonSetupEvent event) {
schematicReceiver = new ServerSchematicLoader();
frequencyHandler = new FrequencyHandler();
constructHandler = new MovingConstructHandler();
logisticalNetworkHandler = new LogisticalNetworkHandler();
torquePropagator = new TorquePropagator();

View file

@ -44,7 +44,6 @@ public class Events {
public static void onLoadWorld(WorldEvent.Load event) {
IWorld world = event.getWorld();
Create.frequencyHandler.onLoadWorld(world);
Create.constructHandler.onLoadWorld(world);
Create.logisticalNetworkHandler.onLoadWorld(world);
Create.torquePropagator.onLoadWorld(world);
}
@ -53,7 +52,6 @@ public class Events {
public static void onUnloadWorld(WorldEvent.Unload event) {
IWorld world = event.getWorld();
Create.frequencyHandler.onUnloadWorld(world);
Create.constructHandler.onUnloadWorld(world);
Create.logisticalNetworkHandler.onUnloadWorld(world);
Create.torquePropagator.onUnloadWorld(world);
}

View file

@ -31,6 +31,7 @@ public class SuperByteBuffer {
// Vertex Lighting
private boolean shouldLight;
private IVertexLighter vertexLighter;
private float lightOffsetX, lightOffsetY, lightOffsetZ;
private int packedLightCoords;
// Vertex Coloring
@ -84,7 +85,8 @@ public class SuperByteBuffer {
if (shouldLight) {
if (vertexLighter != null)
putLight(mutable, vertex, vertexLighter.getPackedLight(x2, y2, z2));
putLight(mutable, vertex,
vertexLighter.getPackedLight(x2 + lightOffsetX, y2 + lightOffsetY, z2 + lightOffsetZ));
else
putLight(mutable, vertex, packedLightCoords);
}
@ -153,6 +155,7 @@ public class SuperByteBuffer {
public SuperByteBuffer light(int packedLightCoords) {
shouldLight = true;
vertexLighter = null;
this.packedLightCoords = packedLightCoords;
return this;
}
@ -163,6 +166,13 @@ public class SuperByteBuffer {
return this;
}
public SuperByteBuffer offsetLighting(double x, double y, double z) {
lightOffsetX = (float) x;
lightOffsetY = (float) y;
lightOffsetZ = (float) z;
return this;
}
public SuperByteBuffer color(int color) {
shouldColor = true;
r = ((color >> 16) & 0xFF);

View file

@ -20,6 +20,8 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.modules.contraptions.receivers.SawBlock;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
import com.simibubi.create.modules.contraptions.receivers.constructs.mounted.MountedContraption;
import com.simibubi.create.modules.contraptions.receivers.constructs.piston.PistonContraption;
import net.minecraft.block.BlockState;
import net.minecraft.block.FallingBlock;
@ -117,13 +119,13 @@ public class Contraption {
return cachedColliders;
}
protected boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
public boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
List<BlockPos> frontier = new ArrayList<>();
Set<BlockPos> visited = new HashSet<>();
anchor = pos;
if (constructCollisionBox == null)
constructCollisionBox = new AxisAlignedBB(pos);
constructCollisionBox = new AxisAlignedBB(BlockPos.ZERO);
frontier.add(pos);
if (!addToInitialFrontier(world, pos, direction, frontier))
@ -433,12 +435,24 @@ public class Contraption {
return compoundnbt;
}
protected void add(BlockPos pos, BlockInfo block) {
BlockInfo blockInfo = new BlockInfo(pos, block.state, block.nbt);
blocks.put(pos, blockInfo);
public void add(BlockPos pos, BlockInfo block) {
BlockPos localPos = pos.subtract(anchor);
BlockInfo blockInfo = new BlockInfo(localPos, block.state, block.nbt);
blocks.put(localPos, blockInfo);
if (block.state.getBlock() instanceof IHaveMovementBehavior)
getActors().add(MutablePair.of(blockInfo, null));
constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(pos));
constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(localPos));
}
public static Contraption fromNBT(CompoundNBT nbt) {
String type = nbt.getString("Type");
Contraption contraption = new Contraption();
if (type.equals("Piston"))
contraption = new PistonContraption();
if (type.equals("Mounted"))
contraption = new MountedContraption();
contraption.readNBT(nbt);
return contraption;
}
public void readNBT(CompoundNBT nbt) {
@ -469,6 +483,12 @@ public class Contraption {
public CompoundNBT writeNBT() {
CompoundNBT nbt = new CompoundNBT();
if (this instanceof PistonContraption)
nbt.putString("Type", "Piston");
if (this instanceof MountedContraption)
nbt.putString("Type", "Mounted");
ListNBT blocks = new ListNBT();
for (BlockInfo block : this.blocks.values()) {
CompoundNBT c = new CompoundNBT();
@ -520,7 +540,12 @@ public class Contraption {
return CreateConfig.parameters.freezePistonConstructs.get();
}
public void disassemble(IWorld world, BlockPos offset, BiPredicate<BlockPos, BlockState> customPlacement) {
public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch) {
disassemble(world, offset, yaw, pitch, (pos, state) -> false);
}
public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch,
BiPredicate<BlockPos, BlockState> customPlacement) {
for (BlockInfo block : blocks.values()) {
BlockPos targetPos = block.pos.add(offset);
BlockState state = block.state;
@ -550,4 +575,8 @@ public class Contraption {
return actors;
}
public BlockPos getAnchor() {
return anchor;
}
}

View file

@ -31,7 +31,7 @@ public class ContraptionRenderer {
public static void render(World world, Contraption c, Consumer<SuperByteBuffer> transform, BufferBuilder buffer) {
SuperByteBuffer contraptionBuffer = CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c));
transform.accept(contraptionBuffer);
buffer.putBulkData(contraptionBuffer.build());
contraptionBuffer.light((lx, ly, lz) -> world.getCombinedLight(new BlockPos(lx, ly, lz), 0)).renderInto(buffer);
renderActors(world, c, transform, buffer);
}

View file

@ -2,6 +2,7 @@ package com.simibubi.create.modules.contraptions.receivers.constructs.mounted;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.RenderUtilityBlock;
import com.simibubi.create.modules.contraptions.receivers.constructs.Contraption;
import net.minecraft.block.AbstractRailBlock;
import net.minecraft.block.Block;
@ -72,7 +73,7 @@ public class CartAssemblerBlock extends AbstractRailBlock {
if (!cart.getPassengers().isEmpty())
return;
MountedContraption contraption = MountedContraption.assembleMinecart(world, pos, cart);
Contraption contraption = MountedContraption.assembleMinecart(world, pos, cart);
ContraptionEntity entity = new ContraptionEntity(world, contraption,
ContraptionEntity.yawFromMotion(cart.getMotion()));
entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
@ -86,11 +87,11 @@ public class CartAssemblerBlock extends AbstractRailBlock {
Entity entity = cart.getPassengers().get(0);
if (!(entity instanceof ContraptionEntity))
return;
MountedContraption contraption = ((ContraptionEntity) entity).contraption;
Contraption contraption = ((ContraptionEntity) entity).getContraption();
if (contraption == null)
return;
contraption.disassemble(world, pos.subtract(contraption.getAnchor()), (targetPos, state) -> {
contraption.disassemble(world, pos.subtract(contraption.getAnchor()), 0, 0, (targetPos, state) -> {
return targetPos.equals(pos);
});

View file

@ -2,35 +2,36 @@ package com.simibubi.create.modules.contraptions.receivers.constructs.mounted;
import com.simibubi.create.AllEntities;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.receivers.constructs.Contraption;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.network.IPacket;
import net.minecraft.network.PacketBuffer;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.util.DamageSource;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.network.FMLPlayMessages.SpawnEntity;
import net.minecraftforge.fml.network.NetworkHooks;
public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnData {
protected MountedContraption contraption;
private Contraption contraption;
protected float initialAngle;
enum MovementType {
TRANSLATION, ROTATION, MOUNTED;
}
// Not synchronizing any of these
protected BlockPos controllerPos;
protected IControlContraption controllerTE;
// Not synchronizing any of these yet
public float targetYaw;
public float targetPitch;
public float contraptionYaw;
@ -44,7 +45,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
this(AllEntities.CONTRAPTION.type, world);
}
public ContraptionEntity(World world, MountedContraption contraption, float initialAngle) {
public ContraptionEntity(World world, Contraption contraption, float initialAngle) {
this(world);
this.contraption = contraption;
this.initialAngle = initialAngle;
@ -53,16 +54,19 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
this.targetYaw = initialAngle;
}
@Override
protected void registerData() {
public <T extends TileEntity & IControlContraption> ContraptionEntity controlledBy(T controller) {
this.controllerPos = controller.getPos();
this.controllerTE = controller;
return this;
}
@Override
public void tick() {
super.tick();
attachToController();
Entity e = getRidingEntity();
if (e == null)
remove();
return;
else {
Vec3d movementVector = e.getMotion();
Vec3d motion = movementVector.normalize();
@ -86,7 +90,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
}
public void tickActors(Vec3d movementVector) {
contraption.getActors().forEach(pair -> {
getContraption().getActors().forEach(pair -> {
MovementContext context = pair.right;
float deg = -contraptionYaw + initialAngle;
context.motion = VecHelper.rotate(movementVector, deg, Axis.Y);
@ -94,15 +98,15 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (context.world == null)
context.world = world;
Vec3d offset = new Vec3d(pair.left.pos.subtract(contraption.getAnchor()));
Vec3d offset = new Vec3d(pair.left.pos.subtract(getContraption().getAnchor()));
world.addParticle(ParticleTypes.BUBBLE, offset.x, offset.y, offset.z, 0, 0, 0);
offset = VecHelper.rotate(offset, deg, Axis.Y);
world.addParticle(ParticleTypes.CRIT, offset.x, offset.y, offset.z, 0, 0, 0);
offset = offset.add(new Vec3d(getPosition()).add(0.5, 0, 0.5));
world.addParticle(ParticleTypes.NOTE, offset.x, offset.y, offset.z, 0, 10, 0);
if (world.isRemote)
return;
@ -116,6 +120,20 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
});
}
@Override
public void setPosition(double x, double y, double z) {
this.posX = x;
this.posY = y;
this.posZ = z;
if (this.isAddedToWorld() && !this.world.isRemote && world instanceof ServerWorld)
((ServerWorld) this.world).chunkCheck(this); // Forge - Process chunk registration after moving.
if (contraption != null) {
AxisAlignedBB cbox = contraption.getCollisionBoxFront();
if (cbox != null)
this.setBoundingBox(cbox.offset(x, y, z));
}
}
public static float yawFromMotion(Vec3d motion) {
return (float) ((Math.PI / 2 - Math.atan2(motion.z, motion.x)) / Math.PI * 180);
}
@ -137,49 +155,46 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
return current + shortest_angle * pct;
}
public boolean hitByEntity(Entity entityIn) {
return entityIn instanceof PlayerEntity
? this.attackEntityFrom(DamageSource.causePlayerDamage((PlayerEntity) entityIn), 0.0F)
: false;
}
public boolean attackEntityFrom(DamageSource source, float amount) {
if (this.isInvulnerableTo(source)) {
return false;
} else {
if (this.isAlive() && !this.world.isRemote) {
this.remove();
this.markVelocityChanged();
}
return true;
}
}
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
@SuppressWarnings("unchecked")
EntityType.Builder<ContraptionEntity> entityBuilder = (EntityType.Builder<ContraptionEntity>) builder;
return entityBuilder.setCustomClientFactory(ContraptionEntity::spawn).size(1, 1);
return entityBuilder.size(1, 1);
}
public static ContraptionEntity spawn(SpawnEntity spawnEntity, World world) {
return new ContraptionEntity(world);
@Override
protected void registerData() {
}
@Override
protected void readAdditional(CompoundNBT compound) {
contraption = new MountedContraption();
contraption.readNBT(compound.getCompound("Contraption"));
contraption = Contraption.fromNBT(compound.getCompound("Contraption"));
initialAngle = compound.getFloat("InitialAngle");
if (compound.contains("Controller"))
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
prevRotationYaw = initialAngle;
contraptionYaw = initialAngle;
targetYaw = initialAngle;
}
public void attachToController() {
if (controllerPos != null && controllerTE == null) {
if (!world.isBlockPresent(controllerPos))
return;
TileEntity te = world.getTileEntity(controllerPos);
if (te == null || !(te instanceof IControlContraption))
remove();
IControlContraption controllerTE = (IControlContraption) te;
this.controllerTE = controllerTE;
controllerTE.attach(this);
}
}
@Override
protected void writeAdditional(CompoundNBT compound) {
compound.put("Contraption", contraption.writeNBT());
compound.put("Contraption", getContraption().writeNBT());
compound.putFloat("InitialAngle", initialAngle);
if (controllerPos != null)
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
}
@Override
@ -199,4 +214,15 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
readAdditional(additionalData.readCompoundTag());
}
public void disassemble() {
if (getContraption() != null)
getContraption().disassemble(world, new BlockPos(getPositionVec().add(.5, .5, .5)), contraptionYaw,
contraptionPitch);
remove();
}
public Contraption getContraption() {
return contraption;
}
}

View file

@ -2,9 +2,9 @@ package com.simibubi.create.modules.contraptions.receivers.constructs.mounted;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager;
@ -13,7 +13,6 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
@ -32,18 +31,17 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
public void doRender(ContraptionEntity entity, double x, double y, double z, float yaw, float partialTicks) {
if (!entity.isAlive())
return;
if (entity.contraption == null)
if (entity.getContraption() == null)
return;
GlStateManager.pushMatrix();
GlStateManager.translated(0, .5, 0);
float angleYaw = (float) (entity.getYaw(partialTicks) / 180 * Math.PI);
float anglePitch = (float) (entity.getPitch(partialTicks) / 180 * Math.PI);
Entity ridingEntity = entity.getRidingEntity();
if (ridingEntity != null && ridingEntity instanceof AbstractMinecartEntity) {
AbstractMinecartEntity cart = (AbstractMinecartEntity) ridingEntity;
GlStateManager.translated(0, .5, 0);
long i = (long) entity.getEntityId() * 493286711L;
i = i * i * 4392167121L + i * 98761L;
@ -74,21 +72,27 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
}
}
BlockPos anchor = entity.contraption.getAnchor();
Vec3d rotationOffset = VecHelper.getCenterOf(anchor);
// BlockPos anchor = entity.getContraption().getAnchor();
// Vec3d rotationOffset = VecHelper.getCenterOf(anchor);
// Vec3d offset = VecHelper.getCenterOf(anchor).scale(-1);
TessellatorHelper.prepareFastRender();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
ContraptionRenderer.render(entity.world, entity.contraption, superByteBuffer -> {
superByteBuffer.translate(-rotationOffset.x, -rotationOffset.y, -rotationOffset.z);
ContraptionRenderer.render(entity.world, entity.getContraption(), superByteBuffer -> {
// superByteBuffer.translate(-rotationOffset.x, -rotationOffset.y, -rotationOffset.z);
superByteBuffer.rotate(Axis.Y, angleYaw);
superByteBuffer.rotate(Axis.Z, anglePitch);
superByteBuffer.translate(x, y, z);
superByteBuffer.offsetLighting(-x + entity.posX, -y + entity.posY, -z + entity.posZ);
}, Tessellator.getInstance().getBuffer());
TessellatorHelper.draw();
GlStateManager.popMatrix();
GlStateManager.shadeModel(7424);
GlStateManager.alphaFunc(516, 0.1F);
GlStateManager.matrixMode(5888);
RenderHelper.enableStandardItemLighting();
super.doRender(entity, x, y, z, yaw, partialTicks);
}

View file

@ -0,0 +1,7 @@
package com.simibubi.create.modules.contraptions.receivers.constructs.mounted;
public interface IControlContraption {
public void attach(ContraptionEntity contraption);
}

View file

@ -26,7 +26,7 @@ import net.minecraft.world.gen.feature.template.Template.BlockInfo;
public class MountedContraption extends Contraption {
public static MountedContraption assembleMinecart(World world, BlockPos pos, AbstractMinecartEntity cart) {
public static Contraption assembleMinecart(World world, BlockPos pos, AbstractMinecartEntity cart) {
if (isFrozen())
return null;
@ -34,7 +34,7 @@ public class MountedContraption extends Contraption {
if (!state.has(RAIL_SHAPE))
return null;
MountedContraption contraption = new MountedContraption();
Contraption contraption = new MountedContraption();
Vec3d vec = cart.getMotion();
if (!contraption.searchMovedStructure(world, pos, Direction.getFacingFromVector(vec.x, vec.y, vec.z)))
return null;
@ -83,8 +83,4 @@ public class MountedContraption extends Contraption {
return capture;
}
public BlockPos getAnchor() {
return anchor;
}
}

View file

@ -1,20 +1,14 @@
package com.simibubi.create.modules.contraptions.receivers.constructs.piston;
import static com.simibubi.create.CreateConfig.parameters;
import static com.simibubi.create.modules.contraptions.receivers.constructs.piston.MechanicalPistonBlock.STATE;
import java.util.Arrays;
import java.util.Iterator;
import org.apache.commons.lang3.tuple.MutablePair;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.Create;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MoverType;
import com.simibubi.create.modules.contraptions.receivers.constructs.mounted.ContraptionEntity;
import com.simibubi.create.modules.contraptions.receivers.constructs.mounted.IControlContraption;
import com.simibubi.create.modules.contraptions.receivers.constructs.piston.MechanicalPistonBlock.PistonState;
import net.minecraft.block.Blocks;
@ -30,14 +24,16 @@ import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class MechanicalPistonTileEntity extends KineticTileEntity {
public class MechanicalPistonTileEntity extends KineticTileEntity implements IControlContraption {
protected PistonContraption movedContraption;
protected float offset;
protected boolean running;
protected boolean assembleNextTick;
protected boolean hadCollisionWithOtherPiston;
protected ContraptionEntity movedContraption;
protected int extensionLength;
public MechanicalPistonTileEntity() {
super(AllTileEntities.MECHANICAL_PISTON.type);
}
@ -71,9 +67,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
public CompoundNBT write(CompoundNBT tag) {
tag.putBoolean("Running", running);
tag.putFloat("Offset", offset);
if (running && !PistonContraption.isFrozen())
tag.put("Construct", movedContraption.writeNBT());
tag.putInt("ExtensionLength", extensionLength);
return super.write(tag);
}
@ -81,76 +75,40 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
public void read(CompoundNBT tag) {
running = tag.getBoolean("Running");
offset = tag.getFloat("Offset");
if (running && !PistonContraption.isFrozen()) {
movedContraption = new PistonContraption();
movedContraption.readNBT(tag.getCompound("Construct"));
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors()) {
MovementContext context = new MovementContext(pair.left.state, MoverType.PISTON);
context.world = world;
Direction direction = getBlockState().get(BlockStateProperties.FACING);
context.motion = new Vec3d(direction.getDirectionVec()).scale(getMovementSpeed()).normalize();
context.currentGridPos = pair.left.pos.offset(direction, getModulatedOffset(offset));
pair.setRight(context);
}
}
extensionLength = tag.getInt("ExtensionLength");
super.read(tag);
}
protected void onBlockVisited(float newOffset) {
if (PistonContraption.isFrozen())
return;
Direction direction = getBlockState().get(BlockStateProperties.FACING);
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors()) {
BlockInfo block = pair.left;
MovementContext context = pair.right;
BlockPos newPos = block.pos.offset(direction, getModulatedOffset(newOffset));
context.currentGridPos = newPos;
IHaveMovementBehavior actor = (IHaveMovementBehavior) block.state.getBlock();
actor.visitPosition(context);
}
}
public void assembleConstruct() {
Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct
movedContraption = PistonContraption.movePistonAt(world, pos, direction, getMovementSpeed() < 0);
if (movedContraption == null)
PistonContraption contraption = PistonContraption.movePistonAt(world, pos, direction, getMovementSpeed() < 0);
if (contraption == null)
return;
// Check if not at limit already
float resultingOffset = movedContraption.initialExtensionProgress + getMovementSpeed();
if (resultingOffset <= 0 || resultingOffset >= movedContraption.extensionLength) {
movedContraption = null;
return;
}
if (hasBlockCollisions(resultingOffset + .5f)) {
movedContraption = null;
float resultingOffset = contraption.initialExtensionProgress + Math.signum(getMovementSpeed()) * .5f;
extensionLength = contraption.extensionLength;
if (resultingOffset <= 0 || resultingOffset >= extensionLength) {
return;
}
// Run
running = true;
offset = movedContraption.initialExtensionProgress;
if (!world.isRemote)
Create.constructHandler.add(this);
offset = contraption.initialExtensionProgress;
sendData();
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66);
for (BlockInfo block : movedContraption.blocks.values()) {
BlockPos startPos = block.pos.offset(direction, movedContraption.initialExtensionProgress);
if (startPos.equals(pos))
for (BlockInfo block : contraption.blocks.values()) {
BlockPos startPos = block.pos.offset(direction, contraption.initialExtensionProgress);
BlockPos add = startPos.add(contraption.getAnchor());
if (add.equals(pos))
continue;
getWorld().setBlockState(startPos, Blocks.AIR.getDefaultState(), 67);
getWorld().setBlockState(add, Blocks.AIR.getDefaultState(), 67);
}
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors()) {
for (MutablePair<BlockInfo, MovementContext> pair : contraption.getActors()) {
MovementContext context = new MovementContext(pair.left.state, MoverType.PISTON);
context.world = world;
context.motion = new Vec3d(direction.getDirectionVec()).scale(getMovementSpeed()).normalize();
@ -158,28 +116,19 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
pair.setRight(context);
}
onBlockVisited(offset);
movedContraption = new ContraptionEntity(getWorld(), contraption, 0).controlledBy(this);
moveContraption();
world.addEntity(movedContraption);
}
public void disassembleConstruct() {
if (!running)
return;
Direction direction = getBlockState().get(BlockStateProperties.FACING);
if (!removed)
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3);
movedContraption.disassemble(world, BlockPos.ZERO.offset(direction, getModulatedOffset(offset)),
(targetPos, state) -> {
if (targetPos.equals(pos)) {
if (!AllBlocks.PISTON_POLE.typeOf(state) && !removed)
world.setBlockState(pos, getBlockState().with(STATE, PistonState.RETRACTED), 3);
return true;
}
return false;
});
movedContraption.disassemble();
running = false;
if (!world.isRemote)
Create.constructHandler.remove(this);
movedContraption = null;
sendData();
@ -196,13 +145,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
if (running) {
if (getSpeed() == 0)
disassembleConstruct();
else {
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors())
pair.right.motion = new Vec3d(
getBlockState().get(BlockStateProperties.FACING).getDirectionVec())
.scale(getMovementSpeed());
else
sendData();
}
return;
}
assembleConstruct();
@ -213,120 +157,114 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
return;
float movementSpeed = getMovementSpeed();
Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
float newOffset = offset + movementSpeed;
MovingConstructHandler.moveEntities(this, movementSpeed, movementDirection, newOffset);
if (world.isRemote) {
offset = newOffset;
if (movedContraption == null)
return;
}
if (getModulatedOffset(newOffset) != getModulatedOffset(offset)) {
onBlockVisited(newOffset);
}
float movement = .5f + (movementSpeed < 0 ? -1f : 0);
if (getModulatedOffset(newOffset + movement) != getModulatedOffset(offset + movement)) {
if (hasBlockCollisions(newOffset + movement)) {
disassembleConstruct();
if (hadCollisionWithOtherPiston)
hadCollisionWithOtherPiston = false;
else if (movementSpeed > 0)
assembleNextTick = true;
return;
}
if (!world.isRemote && getModulatedOffset(newOffset) != getModulatedOffset(offset)) {
offset = newOffset;
sendData();
}
offset = newOffset;
moveContraption();
if (offset <= 0 || offset >= movedContraption.extensionLength) {
disassembleConstruct();
if (offset <= 0 || offset >= extensionLength) {
offset = offset <= 0 ? 0 : extensionLength;
if (!world.isRemote)
disassembleConstruct();
return;
}
}
private boolean hasBlockCollisions(float newOffset) {
if (PistonContraption.isFrozen())
return true;
Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
BlockPos relativePos = BlockPos.ZERO.offset(movementDirection, getModulatedOffset(newOffset));
// Other moving Pistons
int maxPossibleRange = parameters.maxPistonPoles.get() + parameters.maxChassisRange.get()
+ parameters.maxChassisForTranslation.get();
Iterator<MechanicalPistonTileEntity> iterator = Create.constructHandler.getOtherMovingPistonsInWorld(this)
.iterator();
pistonLoop: while (iterator.hasNext()) {
MechanicalPistonTileEntity otherPiston = iterator.next();
if (otherPiston == this)
continue;
if (!otherPiston.running || otherPiston.movedContraption == null) {
iterator.remove();
continue;
}
if (otherPiston.pos.manhattanDistance(pos) > maxPossibleRange * 2)
continue;
Direction otherMovementDirection = otherPiston.getBlockState().get(BlockStateProperties.FACING);
BlockPos otherRelativePos = BlockPos.ZERO.offset(otherMovementDirection,
getModulatedOffset(otherPiston.offset));
for (AxisAlignedBB tBB : Arrays.asList(movedContraption.constructCollisionBox,
movedContraption.pistonCollisionBox)) {
for (AxisAlignedBB oBB : Arrays.asList(otherPiston.movedContraption.constructCollisionBox,
otherPiston.movedContraption.pistonCollisionBox)) {
if (tBB == null || oBB == null)
continue;
boolean frontalCollision = otherMovementDirection == movementDirection.getOpposite();
BlockPos thisColliderOffset = relativePos.offset(movementDirection,
frontalCollision ? (getMovementSpeed() > 0 ? 1 : -1) : 0);
AxisAlignedBB thisBB = tBB.offset(thisColliderOffset);
AxisAlignedBB otherBB = oBB.offset(otherRelativePos);
if (thisBB.intersects(otherBB)) {
boolean actuallyColliding = false;
for (BlockPos colliderPos : movedContraption.getColliders(world, movementDirection)) {
colliderPos = colliderPos.add(thisColliderOffset).subtract(otherRelativePos);
if (!otherPiston.movedContraption.blocks.containsKey(colliderPos))
continue;
actuallyColliding = true;
}
if (!actuallyColliding)
continue pistonLoop;
hadCollisionWithOtherPiston = true;
return true;
}
}
}
public void moveContraption() {
if (movedContraption != null) {
Vec3d constructOffset = getConstructOffset(0.5f);
Vec3d vec = constructOffset.add(new Vec3d(movedContraption.getContraption().getAnchor()));
movedContraption.setPosition(vec.x, vec.y, vec.z);
}
if (!running)
return false;
// Other Blocks in world
for (BlockPos pos : movedContraption.getColliders(world,
getMovementSpeed() > 0 ? movementDirection : movementDirection.getOpposite())) {
BlockPos colliderPos = pos.add(relativePos);
if (!world.isBlockPresent(colliderPos))
return true;
if (!world.getBlockState(colliderPos).getMaterial().isReplaceable()
&& !world.getBlockState(colliderPos).getCollisionShape(world, colliderPos).isEmpty())
return true;
}
return false;
}
// private boolean hasBlockCollisions(float newOffset) {
// if (PistonContraption.isFrozen())
// return true;
//
// Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
// BlockPos relativePos = BlockPos.ZERO.offset(movementDirection, getModulatedOffset(newOffset));
//
// // Other moving Pistons
// int maxPossibleRange = parameters.maxPistonPoles.get() + parameters.maxChassisRange.get()
// + parameters.maxChassisForTranslation.get();
// Iterator<MechanicalPistonTileEntity> iterator = Create.constructHandler.getOtherMovingPistonsInWorld(this)
// .iterator();
// pistonLoop: while (iterator.hasNext()) {
// MechanicalPistonTileEntity otherPiston = iterator.next();
//
// if (otherPiston == this)
// continue;
// if (!otherPiston.running || otherPiston.movedContraption == null) {
// iterator.remove();
// continue;
// }
// if (otherPiston.pos.manhattanDistance(pos) > maxPossibleRange * 2)
// continue;
//
// Direction otherMovementDirection = otherPiston.getBlockState().get(BlockStateProperties.FACING);
// BlockPos otherRelativePos = BlockPos.ZERO.offset(otherMovementDirection,
// getModulatedOffset(otherPiston.offset));
//
// for (AxisAlignedBB tBB : Arrays.asList(movedContraption.constructCollisionBox,
// movedContraption.pistonCollisionBox)) {
// for (AxisAlignedBB oBB : Arrays.asList(otherPiston.movedContraption.constructCollisionBox,
// otherPiston.movedContraption.pistonCollisionBox)) {
// if (tBB == null || oBB == null)
// continue;
//
// boolean frontalCollision = otherMovementDirection == movementDirection.getOpposite();
// BlockPos thisColliderOffset = relativePos.offset(movementDirection,
// frontalCollision ? (getMovementSpeed() > 0 ? 1 : -1) : 0);
// AxisAlignedBB thisBB = tBB.offset(thisColliderOffset);
// AxisAlignedBB otherBB = oBB.offset(otherRelativePos);
//
// if (thisBB.intersects(otherBB)) {
// boolean actuallyColliding = false;
// for (BlockPos colliderPos : movedContraption.getColliders(world, movementDirection)) {
// colliderPos = colliderPos.add(thisColliderOffset).subtract(otherRelativePos);
// if (!otherPiston.movedContraption.blocks.containsKey(colliderPos))
// continue;
// actuallyColliding = true;
// }
// if (!actuallyColliding)
// continue pistonLoop;
// hadCollisionWithOtherPiston = true;
// return true;
// }
//
// }
// }
//
// }
//
// if (!running)
// return false;
//
// // Other Blocks in world
// for (BlockPos pos : movedContraption.getColliders(world,
// getMovementSpeed() > 0 ? movementDirection : movementDirection.getOpposite())) {
// BlockPos colliderPos = pos.add(relativePos);
//
// if (!world.isBlockPresent(colliderPos))
// return true;
// if (!world.getBlockState(colliderPos).getMaterial().isReplaceable()
// && !world.getBlockState(colliderPos).getCollisionShape(world, colliderPos).isEmpty())
// return true;
// }
//
// return false;
// }
private int getModulatedOffset(float offset) {
return MathHelper.clamp((int) (offset + .5f), 0, movedContraption.extensionLength);
return MathHelper.clamp((int) (offset + .5f), 0, extensionLength);
}
public float getMovementSpeed() {
@ -338,8 +276,17 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
public Vec3d getConstructOffset(float partialTicks) {
float interpolatedOffset = MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0,
movedContraption.extensionLength);
extensionLength);
return new Vec3d(getBlockState().get(BlockStateProperties.FACING).getDirectionVec()).scale(interpolatedOffset);
}
@Override
public void attach(ContraptionEntity contraption) {
if (contraption.getContraption() instanceof PistonContraption) {
this.movedContraption = contraption;
if (!world.isRemote)
sendData();
}
}
}

View file

@ -4,12 +4,10 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.math.Vec3d;
public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRenderer {
@ -17,14 +15,6 @@ public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRendere
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) {
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer);
MechanicalPistonTileEntity pistonTe = (MechanicalPistonTileEntity) te;
if (!pistonTe.running)
return;
Vec3d offset = pistonTe.getConstructOffset(partialTicks).subtract(new Vec3d(pistonTe.getPos()));
ContraptionRenderer.render(getWorld(), pistonTe.movedContraption, (superBuffer) -> {
superBuffer.translate(x + offset.x, y + offset.y, z + offset.z);
}, buffer);
}
@Override

View file

@ -1,32 +1,15 @@
package com.simibubi.create.modules.contraptions.receivers.constructs.piston;
/*package com.simibubi.create.modules.contraptions.receivers.constructs.piston;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import com.simibubi.create.Create;
import com.simibubi.create.modules.contraptions.receivers.constructs.Contraption;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.ReuseableStream;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
@ -45,112 +28,112 @@ public class MovingConstructHandler {
Create.logger.debug("Removed Construct List for " + world.getDimension().getType().getRegistryName());
}
public static void moveEntities(MechanicalPistonTileEntity te, float movementSpeed, Direction movementDirection,
float newOffset) {
if (PistonContraption.isFrozen())
return;
World world = te.getWorld();
Vec3d movementVec = new Vec3d(te.getBlockState().get(BlockStateProperties.FACING).getDirectionVec());
Contraption construct = te.movedContraption;
// if (world.isRemote) {
// renderedBBs.clear();
// if (construct.pistonCollisionBox != null)
// renderedBBs.add(construct.pistonCollisionBox.offset(te.getConstructOffset(0)));
// if (construct.constructCollisionBox != null)
// renderedBBs.add(construct.constructCollisionBox.offset(te.getConstructOffset(0)));
// public static void moveEntities(MechanicalPistonTileEntity te, float movementSpeed, Direction movementDirection,
// float newOffset) {
// if (PistonContraption.isFrozen())
// return;
//
// World world = te.getWorld();
// Vec3d movementVec = new Vec3d(te.getBlockState().get(BlockStateProperties.FACING).getDirectionVec());
// Contraption construct = te.movedContraption;
//
//// if (world.isRemote) {
//// renderedBBs.clear();
//// if (construct.pistonCollisionBox != null)
//// renderedBBs.add(construct.pistonCollisionBox.offset(te.getConstructOffset(0)));
//// if (construct.constructCollisionBox != null)
//// renderedBBs.add(construct.constructCollisionBox.offset(te.getConstructOffset(0)));
////
//// }
//
// if (construct.getCollisionBoxFront() != null) {
// AxisAlignedBB constructBB = construct.getCollisionBoxFront().offset(te.getConstructOffset(0)).grow(.5f);
//
// for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, constructBB,
// e -> e.getPushReaction() == PushReaction.NORMAL)) {
//
// AxisAlignedBB entityScanBB = entity.getBoundingBox().offset(movementVec.scale(-1 * newOffset))
// .grow(.5f);
// BlockPos min = new BlockPos(entityScanBB.minX, entityScanBB.minY, entityScanBB.minZ);
// BlockPos max = new BlockPos(entityScanBB.maxX, entityScanBB.maxY, entityScanBB.maxZ);
//
// Stream<VoxelShape> hits = BlockPos.getAllInBox(min, max).filter(construct.blocks::containsKey)
// .map(pos -> {
// Vec3d vec = new Vec3d(pos).add(te.getConstructOffset(te.getMovementSpeed() > 0 ? 1 : 0));
// return construct.blocks.get(pos).state.getShape(world, new BlockPos(vec)).withOffset(vec.x,
// vec.y, vec.z);
// });
// ReuseableStream<VoxelShape> potentialHits = new ReuseableStream<>(hits);
//
// AxisAlignedBB entityBB = entity.getBoundingBox();
// Vec3d motion = entity.getMotion();
// Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(-movementSpeed).add(motion);
// Vec3d allowedMovement = Entity.getAllowedMovement(movement, entityBB, world,
// ISelectionContext.forEntity(entity), potentialHits);
//
// for (Object shape : potentialHits.createStream().toArray()) {
// VoxelShape voxelShape = (VoxelShape) shape;
// if (!entityBB.intersects(voxelShape.getBoundingBox()))
// continue;
//
// Direction bestSide = Direction.DOWN;
// double bestOffset = 100;
// double finalOffset = 0;
//
// for (Direction face : Direction.values()) {
// Axis axis = face.getAxis();
// double d = axis == Axis.X ? entityBB.getXSize()
// : axis == Axis.Y ? entityBB.getYSize() : entityBB.getZSize();
// d = d + 1.5f;
//
// Vec3d nudge = new Vec3d(face.getDirectionVec()).scale(d);
// AxisAlignedBB nudgedBB = entityBB.offset(nudge.getX(), nudge.getY(), nudge.getZ());
// double nudgeDistance = face.getAxisDirection() == AxisDirection.POSITIVE ? -d : d;
// double offset = voxelShape.getAllowedOffset(face.getAxis(), nudgedBB, nudgeDistance);
// double abs = Math.abs(nudgeDistance - offset);
// if (abs < Math.abs(bestOffset) && abs != 0) {
// bestOffset = abs;
// finalOffset = abs;
// bestSide = face;
// }
// }
//
// if (bestOffset != 0) {
// entity.move(MoverType.SELF, new Vec3d(bestSide.getDirectionVec()).scale(finalOffset));
// switch (bestSide.getAxis()) {
// case X:
// entity.setMotion(0, motion.y, motion.z);
// break;
// case Y:
// entity.setMotion(motion.x, bestSide == Direction.UP ? movementSpeed + 1 / 8f : 0, motion.z);
// entity.fall(entity.fallDistance, 1);
// entity.fallDistance = 0;
// entity.onGround = true;
// break;
// case Z:
// entity.setMotion(motion.x, motion.y, 0);
// break;
// }
//
// break;
// }
// }
//
// if (!allowedMovement.equals(movement)) {
// if (allowedMovement.y != movement.y) {
// entity.fall(entity.fallDistance, 1);
// entity.fallDistance = 0;
// entity.onGround = true;
// }
// if (entity instanceof PlayerEntity && !world.isRemote)
// return;
// entity.setMotion(allowedMovement.subtract(movement.subtract(motion)));
// entity.velocityChanged = true;
// }
//
// }
// }
if (construct.getCollisionBoxFront() != null) {
AxisAlignedBB constructBB = construct.getCollisionBoxFront().offset(te.getConstructOffset(0)).grow(.5f);
for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, constructBB,
e -> e.getPushReaction() == PushReaction.NORMAL)) {
AxisAlignedBB entityScanBB = entity.getBoundingBox().offset(movementVec.scale(-1 * newOffset))
.grow(.5f);
BlockPos min = new BlockPos(entityScanBB.minX, entityScanBB.minY, entityScanBB.minZ);
BlockPos max = new BlockPos(entityScanBB.maxX, entityScanBB.maxY, entityScanBB.maxZ);
Stream<VoxelShape> hits = BlockPos.getAllInBox(min, max).filter(construct.blocks::containsKey)
.map(pos -> {
Vec3d vec = new Vec3d(pos).add(te.getConstructOffset(te.getMovementSpeed() > 0 ? 1 : 0));
return construct.blocks.get(pos).state.getShape(world, new BlockPos(vec)).withOffset(vec.x,
vec.y, vec.z);
});
ReuseableStream<VoxelShape> potentialHits = new ReuseableStream<>(hits);
AxisAlignedBB entityBB = entity.getBoundingBox();
Vec3d motion = entity.getMotion();
Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(-movementSpeed).add(motion);
Vec3d allowedMovement = Entity.getAllowedMovement(movement, entityBB, world,
ISelectionContext.forEntity(entity), potentialHits);
for (Object shape : potentialHits.createStream().toArray()) {
VoxelShape voxelShape = (VoxelShape) shape;
if (!entityBB.intersects(voxelShape.getBoundingBox()))
continue;
Direction bestSide = Direction.DOWN;
double bestOffset = 100;
double finalOffset = 0;
for (Direction face : Direction.values()) {
Axis axis = face.getAxis();
double d = axis == Axis.X ? entityBB.getXSize()
: axis == Axis.Y ? entityBB.getYSize() : entityBB.getZSize();
d = d + 1.5f;
Vec3d nudge = new Vec3d(face.getDirectionVec()).scale(d);
AxisAlignedBB nudgedBB = entityBB.offset(nudge.getX(), nudge.getY(), nudge.getZ());
double nudgeDistance = face.getAxisDirection() == AxisDirection.POSITIVE ? -d : d;
double offset = voxelShape.getAllowedOffset(face.getAxis(), nudgedBB, nudgeDistance);
double abs = Math.abs(nudgeDistance - offset);
if (abs < Math.abs(bestOffset) && abs != 0) {
bestOffset = abs;
finalOffset = abs;
bestSide = face;
}
}
if (bestOffset != 0) {
entity.move(MoverType.SELF, new Vec3d(bestSide.getDirectionVec()).scale(finalOffset));
switch (bestSide.getAxis()) {
case X:
entity.setMotion(0, motion.y, motion.z);
break;
case Y:
entity.setMotion(motion.x, bestSide == Direction.UP ? movementSpeed + 1 / 8f : 0, motion.z);
entity.fall(entity.fallDistance, 1);
entity.fallDistance = 0;
entity.onGround = true;
break;
case Z:
entity.setMotion(motion.x, motion.y, 0);
break;
}
break;
}
}
if (!allowedMovement.equals(movement)) {
if (allowedMovement.y != movement.y) {
entity.fall(entity.fallDistance, 1);
entity.fallDistance = 0;
entity.onGround = true;
}
if (entity instanceof PlayerEntity && !world.isRemote)
return;
entity.setMotion(allowedMovement.subtract(movement.subtract(motion)));
entity.velocityChanged = true;
}
}
}
}
// }
public void add(MechanicalPistonTileEntity mechanicalPistonTileEntity) {
movingPistons.get(mechanicalPistonTileEntity.getWorld()).add(mechanicalPistonTileEntity);
@ -181,4 +164,4 @@ public class MovingConstructHandler {
// }
// }
}
}*/

View file

@ -18,9 +18,11 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.PistonType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
@ -39,8 +41,7 @@ public class PistonContraption extends Contraption {
construct.orientation = direction;
if (!construct.collectExtensions(world, pos, direction))
return null;
if (!construct.searchMovedStructure(world, pos.offset(direction, construct.initialExtensionProgress + 1),
retract ? direction.getOpposite() : direction))
if (!construct.searchMovedStructure(world, construct.anchor, retract ? direction.getOpposite() : direction))
return null;
return construct;
}
@ -93,13 +94,18 @@ public class PistonContraption extends Contraption {
initialExtensionProgress = extensionsInFront;
pistonCollisionBox = new AxisAlignedBB(end.offset(direction, -extensionsInFront));
anchor = pos.offset(direction, initialExtensionProgress + 1);
if (extensionLength == 0)
return false;
for (BlockInfo pole : poles) {
BlockPos polePos = pole.pos.offset(direction, -extensionsInFront);
BlockPos polePos = pole.pos.offset(direction, -extensionsInFront).subtract(anchor);
blocks.put(polePos, new BlockInfo(polePos, pole.state, null));
pistonCollisionBox = pistonCollisionBox.union(new AxisAlignedBB(polePos));
}
constructCollisionBox = new AxisAlignedBB(pos.offset(direction, initialExtensionProgress));
constructCollisionBox = new AxisAlignedBB(BlockPos.ZERO.offset(direction, -initialExtensionProgress));
return true;
}
@ -125,14 +131,35 @@ public class PistonContraption extends Contraption {
return true;
}
protected void add(BlockPos pos, BlockInfo block) {
public void add(BlockPos pos, BlockInfo block) {
// super.add(pos, block);
super.add(pos.offset(orientation, -initialExtensionProgress), block);
}
@Override
public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch) {
super.disassemble(world, offset, yaw, pitch, (pos, state) -> {
BlockPos pistonPos = anchor.offset(orientation, -initialExtensionProgress - 1);
BlockState pistonState = world.getBlockState(pistonPos);
TileEntity te = world.getTileEntity(pistonPos);
if (pos.equals(pistonPos)) {
if (te == null || te.isRemoved())
return true;
if (!AllBlocks.PISTON_POLE.typeOf(state) && pistonState.getBlock() instanceof MechanicalPistonBlock)
world.setBlockState(pistonPos, pistonState.with(MechanicalPistonBlock.STATE, PistonState.RETRACTED),
3);
return true;
}
return false;
});
}
@Override
public void readNBT(CompoundNBT nbt) {
super.readNBT(nbt);
extensionLength = nbt.getInt("ExtensionLength");
initialExtensionProgress = nbt.getInt("InitialLength");
orientation = Direction.byIndex(nbt.getInt("Orientation"));
if (nbt.contains("BoundsBack"))
pistonCollisionBox = readAABB(nbt.getList("BoundsBack", 5));
}
@ -145,7 +172,9 @@ public class PistonContraption extends Contraption {
ListNBT bb = writeAABB(pistonCollisionBox);
nbt.put("BoundsBack", bb);
}
nbt.putInt("InitialLength", initialExtensionProgress);
nbt.putInt("ExtensionLength", extensionLength);
nbt.putInt("Orientation", orientation.getIndex());
return nbt;
}