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.AnimationTickHolder;
import com.simibubi.create.foundation.utility.TooltipHelper; import com.simibubi.create.foundation.utility.TooltipHelper;
import com.simibubi.create.modules.contraptions.KineticDebugger; 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.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.TurntableHandler; import com.simibubi.create.modules.contraptions.receivers.TurntableHandler;
import com.simibubi.create.modules.contraptions.relays.belt.BeltConnectorItemHandler; import com.simibubi.create.modules.contraptions.relays.belt.BeltConnectorItemHandler;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;

View File

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

View File

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

View File

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

View File

@ -20,6 +20,8 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig; import com.simibubi.create.CreateConfig;
import com.simibubi.create.modules.contraptions.receivers.SawBlock; 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.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.BlockState;
import net.minecraft.block.FallingBlock; import net.minecraft.block.FallingBlock;
@ -117,13 +119,13 @@ public class Contraption {
return cachedColliders; 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<>(); List<BlockPos> frontier = new ArrayList<>();
Set<BlockPos> visited = new HashSet<>(); Set<BlockPos> visited = new HashSet<>();
anchor = pos; anchor = pos;
if (constructCollisionBox == null) if (constructCollisionBox == null)
constructCollisionBox = new AxisAlignedBB(pos); constructCollisionBox = new AxisAlignedBB(BlockPos.ZERO);
frontier.add(pos); frontier.add(pos);
if (!addToInitialFrontier(world, pos, direction, frontier)) if (!addToInitialFrontier(world, pos, direction, frontier))
@ -433,12 +435,24 @@ public class Contraption {
return compoundnbt; return compoundnbt;
} }
protected void add(BlockPos pos, BlockInfo block) { public void add(BlockPos pos, BlockInfo block) {
BlockInfo blockInfo = new BlockInfo(pos, block.state, block.nbt); BlockPos localPos = pos.subtract(anchor);
blocks.put(pos, blockInfo); BlockInfo blockInfo = new BlockInfo(localPos, block.state, block.nbt);
blocks.put(localPos, blockInfo);
if (block.state.getBlock() instanceof IHaveMovementBehavior) if (block.state.getBlock() instanceof IHaveMovementBehavior)
getActors().add(MutablePair.of(blockInfo, null)); 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) { public void readNBT(CompoundNBT nbt) {
@ -469,6 +483,12 @@ public class Contraption {
public CompoundNBT writeNBT() { public CompoundNBT writeNBT() {
CompoundNBT nbt = new CompoundNBT(); CompoundNBT nbt = new CompoundNBT();
if (this instanceof PistonContraption)
nbt.putString("Type", "Piston");
if (this instanceof MountedContraption)
nbt.putString("Type", "Mounted");
ListNBT blocks = new ListNBT(); ListNBT blocks = new ListNBT();
for (BlockInfo block : this.blocks.values()) { for (BlockInfo block : this.blocks.values()) {
CompoundNBT c = new CompoundNBT(); CompoundNBT c = new CompoundNBT();
@ -520,7 +540,12 @@ public class Contraption {
return CreateConfig.parameters.freezePistonConstructs.get(); 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()) { for (BlockInfo block : blocks.values()) {
BlockPos targetPos = block.pos.add(offset); BlockPos targetPos = block.pos.add(offset);
BlockState state = block.state; BlockState state = block.state;
@ -550,4 +575,8 @@ public class Contraption {
return actors; 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) { public static void render(World world, Contraption c, Consumer<SuperByteBuffer> transform, BufferBuilder buffer) {
SuperByteBuffer contraptionBuffer = CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c)); SuperByteBuffer contraptionBuffer = CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c));
transform.accept(contraptionBuffer); 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); 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.AllBlocks;
import com.simibubi.create.foundation.block.RenderUtilityBlock; 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.AbstractRailBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -72,7 +73,7 @@ public class CartAssemblerBlock extends AbstractRailBlock {
if (!cart.getPassengers().isEmpty()) if (!cart.getPassengers().isEmpty())
return; return;
MountedContraption contraption = MountedContraption.assembleMinecart(world, pos, cart); Contraption contraption = MountedContraption.assembleMinecart(world, pos, cart);
ContraptionEntity entity = new ContraptionEntity(world, contraption, ContraptionEntity entity = new ContraptionEntity(world, contraption,
ContraptionEntity.yawFromMotion(cart.getMotion())); ContraptionEntity.yawFromMotion(cart.getMotion()));
entity.setPosition(pos.getX(), pos.getY(), pos.getZ()); entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
@ -86,11 +87,11 @@ public class CartAssemblerBlock extends AbstractRailBlock {
Entity entity = cart.getPassengers().get(0); Entity entity = cart.getPassengers().get(0);
if (!(entity instanceof ContraptionEntity)) if (!(entity instanceof ContraptionEntity))
return; return;
MountedContraption contraption = ((ContraptionEntity) entity).contraption; Contraption contraption = ((ContraptionEntity) entity).getContraption();
if (contraption == null) if (contraption == null)
return; 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); 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.AllEntities;
import com.simibubi.create.foundation.utility.VecHelper; 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;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext; import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.network.IPacket; import net.minecraft.network.IPacket;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.particles.ParticleTypes; 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.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.network.FMLPlayMessages.SpawnEntity;
import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.fml.network.NetworkHooks;
public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnData { public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnData {
protected MountedContraption contraption; private Contraption contraption;
protected float initialAngle; 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 targetYaw;
public float targetPitch; public float targetPitch;
public float contraptionYaw; public float contraptionYaw;
@ -44,7 +45,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
this(AllEntities.CONTRAPTION.type, world); this(AllEntities.CONTRAPTION.type, world);
} }
public ContraptionEntity(World world, MountedContraption contraption, float initialAngle) { public ContraptionEntity(World world, Contraption contraption, float initialAngle) {
this(world); this(world);
this.contraption = contraption; this.contraption = contraption;
this.initialAngle = initialAngle; this.initialAngle = initialAngle;
@ -53,16 +54,19 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
this.targetYaw = initialAngle; this.targetYaw = initialAngle;
} }
@Override public <T extends TileEntity & IControlContraption> ContraptionEntity controlledBy(T controller) {
protected void registerData() { this.controllerPos = controller.getPos();
this.controllerTE = controller;
return this;
} }
@Override @Override
public void tick() { public void tick() {
super.tick(); super.tick();
attachToController();
Entity e = getRidingEntity(); Entity e = getRidingEntity();
if (e == null) if (e == null)
remove(); return;
else { else {
Vec3d movementVector = e.getMotion(); Vec3d movementVector = e.getMotion();
Vec3d motion = movementVector.normalize(); Vec3d motion = movementVector.normalize();
@ -86,7 +90,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
public void tickActors(Vec3d movementVector) { public void tickActors(Vec3d movementVector) {
contraption.getActors().forEach(pair -> { getContraption().getActors().forEach(pair -> {
MovementContext context = pair.right; MovementContext context = pair.right;
float deg = -contraptionYaw + initialAngle; float deg = -contraptionYaw + initialAngle;
context.motion = VecHelper.rotate(movementVector, deg, Axis.Y); context.motion = VecHelper.rotate(movementVector, deg, Axis.Y);
@ -94,15 +98,15 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (context.world == null) if (context.world == null)
context.world = world; 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); world.addParticle(ParticleTypes.BUBBLE, offset.x, offset.y, offset.z, 0, 0, 0);
offset = VecHelper.rotate(offset, deg, Axis.Y); offset = VecHelper.rotate(offset, deg, Axis.Y);
world.addParticle(ParticleTypes.CRIT, offset.x, offset.y, offset.z, 0, 0, 0); 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)); 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); world.addParticle(ParticleTypes.NOTE, offset.x, offset.y, offset.z, 0, 10, 0);
if (world.isRemote) if (world.isRemote)
return; 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) { public static float yawFromMotion(Vec3d motion) {
return (float) ((Math.PI / 2 - Math.atan2(motion.z, motion.x)) / Math.PI * 180); 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; 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) { public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
EntityType.Builder<ContraptionEntity> entityBuilder = (EntityType.Builder<ContraptionEntity>) builder; 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) { @Override
return new ContraptionEntity(world); protected void registerData() {
} }
@Override @Override
protected void readAdditional(CompoundNBT compound) { protected void readAdditional(CompoundNBT compound) {
contraption = new MountedContraption(); contraption = Contraption.fromNBT(compound.getCompound("Contraption"));
contraption.readNBT(compound.getCompound("Contraption"));
initialAngle = compound.getFloat("InitialAngle"); initialAngle = compound.getFloat("InitialAngle");
if (compound.contains("Controller"))
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
prevRotationYaw = initialAngle; prevRotationYaw = initialAngle;
contraptionYaw = initialAngle; contraptionYaw = initialAngle;
targetYaw = 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 @Override
protected void writeAdditional(CompoundNBT compound) { protected void writeAdditional(CompoundNBT compound) {
compound.put("Contraption", contraption.writeNBT()); compound.put("Contraption", getContraption().writeNBT());
compound.putFloat("InitialAngle", initialAngle); compound.putFloat("InitialAngle", initialAngle);
if (controllerPos != null)
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
} }
@Override @Override
@ -199,4 +214,15 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
readAdditional(additionalData.readCompoundTag()); 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.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.utility.TessellatorHelper; import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer; 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.Tessellator;
import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.client.renderer.entity.EntityRendererManager;
@ -13,7 +13,6 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity; import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
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;
@ -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) { public void doRender(ContraptionEntity entity, double x, double y, double z, float yaw, float partialTicks) {
if (!entity.isAlive()) if (!entity.isAlive())
return; return;
if (entity.contraption == null) if (entity.getContraption() == null)
return; return;
GlStateManager.pushMatrix(); GlStateManager.pushMatrix();
GlStateManager.translated(0, .5, 0);
float angleYaw = (float) (entity.getYaw(partialTicks) / 180 * Math.PI); float angleYaw = (float) (entity.getYaw(partialTicks) / 180 * Math.PI);
float anglePitch = (float) (entity.getPitch(partialTicks) / 180 * Math.PI); float anglePitch = (float) (entity.getPitch(partialTicks) / 180 * Math.PI);
Entity ridingEntity = entity.getRidingEntity(); Entity ridingEntity = entity.getRidingEntity();
if (ridingEntity != null && ridingEntity instanceof AbstractMinecartEntity) { if (ridingEntity != null && ridingEntity instanceof AbstractMinecartEntity) {
AbstractMinecartEntity cart = (AbstractMinecartEntity) ridingEntity; AbstractMinecartEntity cart = (AbstractMinecartEntity) ridingEntity;
GlStateManager.translated(0, .5, 0);
long i = (long) entity.getEntityId() * 493286711L; long i = (long) entity.getEntityId() * 493286711L;
i = i * i * 4392167121L + i * 98761L; i = i * i * 4392167121L + i * 98761L;
@ -74,21 +72,27 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
} }
} }
BlockPos anchor = entity.contraption.getAnchor(); // BlockPos anchor = entity.getContraption().getAnchor();
Vec3d rotationOffset = VecHelper.getCenterOf(anchor); // Vec3d rotationOffset = VecHelper.getCenterOf(anchor);
// Vec3d offset = VecHelper.getCenterOf(anchor).scale(-1); // Vec3d offset = VecHelper.getCenterOf(anchor).scale(-1);
TessellatorHelper.prepareFastRender(); TessellatorHelper.prepareFastRender();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK); TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
ContraptionRenderer.render(entity.world, entity.contraption, superByteBuffer -> { ContraptionRenderer.render(entity.world, entity.getContraption(), superByteBuffer -> {
superByteBuffer.translate(-rotationOffset.x, -rotationOffset.y, -rotationOffset.z); // superByteBuffer.translate(-rotationOffset.x, -rotationOffset.y, -rotationOffset.z);
superByteBuffer.rotate(Axis.Y, angleYaw); superByteBuffer.rotate(Axis.Y, angleYaw);
superByteBuffer.rotate(Axis.Z, anglePitch); superByteBuffer.rotate(Axis.Z, anglePitch);
superByteBuffer.translate(x, y, z); superByteBuffer.translate(x, y, z);
superByteBuffer.offsetLighting(-x + entity.posX, -y + entity.posY, -z + entity.posZ);
}, Tessellator.getInstance().getBuffer()); }, Tessellator.getInstance().getBuffer());
TessellatorHelper.draw(); TessellatorHelper.draw();
GlStateManager.popMatrix(); GlStateManager.popMatrix();
GlStateManager.shadeModel(7424);
GlStateManager.alphaFunc(516, 0.1F);
GlStateManager.matrixMode(5888);
RenderHelper.enableStandardItemLighting();
super.doRender(entity, x, y, z, yaw, partialTicks); 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 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()) if (isFrozen())
return null; return null;
@ -34,7 +34,7 @@ public class MountedContraption extends Contraption {
if (!state.has(RAIL_SHAPE)) if (!state.has(RAIL_SHAPE))
return null; return null;
MountedContraption contraption = new MountedContraption(); Contraption contraption = new MountedContraption();
Vec3d vec = cart.getMotion(); Vec3d vec = cart.getMotion();
if (!contraption.searchMovedStructure(world, pos, Direction.getFacingFromVector(vec.x, vec.y, vec.z))) if (!contraption.searchMovedStructure(world, pos, Direction.getFacingFromVector(vec.x, vec.y, vec.z)))
return null; return null;
@ -83,8 +83,4 @@ public class MountedContraption extends Contraption {
return capture; return capture;
} }
public BlockPos getAnchor() {
return anchor;
}
} }

View File

@ -1,20 +1,14 @@
package com.simibubi.create.modules.contraptions.receivers.constructs.piston; 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 org.apache.commons.lang3.tuple.MutablePair;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.Create;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; 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.MovementContext;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MoverType; 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 com.simibubi.create.modules.contraptions.receivers.constructs.piston.MechanicalPistonBlock.PistonState;
import net.minecraft.block.Blocks; 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.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; 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 float offset;
protected boolean running; protected boolean running;
protected boolean assembleNextTick; protected boolean assembleNextTick;
protected boolean hadCollisionWithOtherPiston; protected boolean hadCollisionWithOtherPiston;
protected ContraptionEntity movedContraption;
protected int extensionLength;
public MechanicalPistonTileEntity() { public MechanicalPistonTileEntity() {
super(AllTileEntities.MECHANICAL_PISTON.type); super(AllTileEntities.MECHANICAL_PISTON.type);
} }
@ -71,9 +67,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
public CompoundNBT write(CompoundNBT tag) { public CompoundNBT write(CompoundNBT tag) {
tag.putBoolean("Running", running); tag.putBoolean("Running", running);
tag.putFloat("Offset", offset); tag.putFloat("Offset", offset);
if (running && !PistonContraption.isFrozen()) tag.putInt("ExtensionLength", extensionLength);
tag.put("Construct", movedContraption.writeNBT());
return super.write(tag); return super.write(tag);
} }
@ -81,76 +75,40 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
public void read(CompoundNBT tag) { public void read(CompoundNBT tag) {
running = tag.getBoolean("Running"); running = tag.getBoolean("Running");
offset = tag.getFloat("Offset"); offset = tag.getFloat("Offset");
if (running && !PistonContraption.isFrozen()) { extensionLength = tag.getInt("ExtensionLength");
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);
}
}
super.read(tag); 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() { public void assembleConstruct() {
Direction direction = getBlockState().get(BlockStateProperties.FACING); Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct // Collect Construct
movedContraption = PistonContraption.movePistonAt(world, pos, direction, getMovementSpeed() < 0); PistonContraption contraption = PistonContraption.movePistonAt(world, pos, direction, getMovementSpeed() < 0);
if (movedContraption == null) if (contraption == null)
return; return;
// Check if not at limit already // Check if not at limit already
float resultingOffset = movedContraption.initialExtensionProgress + getMovementSpeed(); float resultingOffset = contraption.initialExtensionProgress + Math.signum(getMovementSpeed()) * .5f;
if (resultingOffset <= 0 || resultingOffset >= movedContraption.extensionLength) { extensionLength = contraption.extensionLength;
movedContraption = null; if (resultingOffset <= 0 || resultingOffset >= extensionLength) {
return;
}
if (hasBlockCollisions(resultingOffset + .5f)) {
movedContraption = null;
return; return;
} }
// Run // Run
running = true; running = true;
offset = movedContraption.initialExtensionProgress; offset = contraption.initialExtensionProgress;
if (!world.isRemote)
Create.constructHandler.add(this);
sendData(); sendData();
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66); getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66);
for (BlockInfo block : movedContraption.blocks.values()) { for (BlockInfo block : contraption.blocks.values()) {
BlockPos startPos = block.pos.offset(direction, movedContraption.initialExtensionProgress); BlockPos startPos = block.pos.offset(direction, contraption.initialExtensionProgress);
if (startPos.equals(pos)) BlockPos add = startPos.add(contraption.getAnchor());
if (add.equals(pos))
continue; 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); MovementContext context = new MovementContext(pair.left.state, MoverType.PISTON);
context.world = world; context.world = world;
context.motion = new Vec3d(direction.getDirectionVec()).scale(getMovementSpeed()).normalize(); context.motion = new Vec3d(direction.getDirectionVec()).scale(getMovementSpeed()).normalize();
@ -158,28 +116,19 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
pair.setRight(context); pair.setRight(context);
} }
onBlockVisited(offset); movedContraption = new ContraptionEntity(getWorld(), contraption, 0).controlledBy(this);
moveContraption();
world.addEntity(movedContraption);
} }
public void disassembleConstruct() { public void disassembleConstruct() {
if (!running) if (!running)
return; return;
Direction direction = getBlockState().get(BlockStateProperties.FACING);
if (!removed) if (!removed)
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3); getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3);
movedContraption.disassemble(world, BlockPos.ZERO.offset(direction, getModulatedOffset(offset)), movedContraption.disassemble();
(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;
});
running = false; running = false;
if (!world.isRemote)
Create.constructHandler.remove(this);
movedContraption = null; movedContraption = null;
sendData(); sendData();
@ -196,13 +145,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
if (running) { if (running) {
if (getSpeed() == 0) if (getSpeed() == 0)
disassembleConstruct(); disassembleConstruct();
else { else
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors())
pair.right.motion = new Vec3d(
getBlockState().get(BlockStateProperties.FACING).getDirectionVec())
.scale(getMovementSpeed());
sendData(); sendData();
}
return; return;
} }
assembleConstruct(); assembleConstruct();
@ -213,120 +157,114 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
return; return;
float movementSpeed = getMovementSpeed(); float movementSpeed = getMovementSpeed();
Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
float newOffset = offset + movementSpeed; float newOffset = offset + movementSpeed;
MovingConstructHandler.moveEntities(this, movementSpeed, movementDirection, newOffset); if (movedContraption == null)
if (world.isRemote) {
offset = newOffset;
return; return;
} if (!world.isRemote && getModulatedOffset(newOffset) != getModulatedOffset(offset)) {
offset = newOffset;
if (getModulatedOffset(newOffset) != getModulatedOffset(offset)) { sendData();
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;
}
} }
offset = newOffset; offset = newOffset;
moveContraption();
if (offset <= 0 || offset >= movedContraption.extensionLength) { if (offset <= 0 || offset >= extensionLength) {
disassembleConstruct(); offset = offset <= 0 ? 0 : extensionLength;
if (!world.isRemote)
disassembleConstruct();
return; return;
} }
} }
private boolean hasBlockCollisions(float newOffset) { public void moveContraption() {
if (PistonContraption.isFrozen()) if (movedContraption != null) {
return true; Vec3d constructOffset = getConstructOffset(0.5f);
Vec3d vec = constructOffset.add(new Vec3d(movedContraption.getContraption().getAnchor()));
Direction movementDirection = getBlockState().get(BlockStateProperties.FACING); movedContraption.setPosition(vec.x, vec.y, vec.z);
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 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) { 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() { public float getMovementSpeed() {
@ -338,8 +276,17 @@ public class MechanicalPistonTileEntity extends KineticTileEntity {
public Vec3d getConstructOffset(float partialTicks) { public Vec3d getConstructOffset(float partialTicks) {
float interpolatedOffset = MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0, float interpolatedOffset = MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0,
movedContraption.extensionLength); extensionLength);
return new Vec3d(getBlockState().get(BlockStateProperties.FACING).getDirectionVec()).scale(interpolatedOffset); 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.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; 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.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.math.Vec3d;
public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRenderer { 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, public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) { int destroyStage, BufferBuilder buffer) {
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, 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 @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.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Stream;
import com.simibubi.create.Create; 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.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.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber @EventBusSubscriber
@ -45,112 +28,112 @@ public class MovingConstructHandler {
Create.logger.debug("Removed Construct List for " + world.getDimension().getType().getRegistryName()); Create.logger.debug("Removed Construct List for " + world.getDimension().getType().getRegistryName());
} }
public static void moveEntities(MechanicalPistonTileEntity te, float movementSpeed, Direction movementDirection, // public static void moveEntities(MechanicalPistonTileEntity te, float movementSpeed, Direction movementDirection,
float newOffset) { // float newOffset) {
if (PistonContraption.isFrozen()) // if (PistonContraption.isFrozen())
return; // 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)));
// //
// 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) { public void add(MechanicalPistonTileEntity mechanicalPistonTileEntity) {
movingPistons.get(mechanicalPistonTileEntity.getWorld()).add(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.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.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.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;
@ -39,8 +41,7 @@ public class PistonContraption extends Contraption {
construct.orientation = direction; construct.orientation = direction;
if (!construct.collectExtensions(world, pos, direction)) if (!construct.collectExtensions(world, pos, direction))
return null; return null;
if (!construct.searchMovedStructure(world, pos.offset(direction, construct.initialExtensionProgress + 1), if (!construct.searchMovedStructure(world, construct.anchor, retract ? direction.getOpposite() : direction))
retract ? direction.getOpposite() : direction))
return null; return null;
return construct; return construct;
} }
@ -93,13 +94,18 @@ public class PistonContraption extends Contraption {
initialExtensionProgress = extensionsInFront; initialExtensionProgress = extensionsInFront;
pistonCollisionBox = new AxisAlignedBB(end.offset(direction, -extensionsInFront)); pistonCollisionBox = new AxisAlignedBB(end.offset(direction, -extensionsInFront));
anchor = pos.offset(direction, initialExtensionProgress + 1);
if (extensionLength == 0)
return false;
for (BlockInfo pole : poles) { 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)); blocks.put(polePos, new BlockInfo(polePos, pole.state, null));
pistonCollisionBox = pistonCollisionBox.union(new AxisAlignedBB(polePos)); pistonCollisionBox = pistonCollisionBox.union(new AxisAlignedBB(polePos));
} }
constructCollisionBox = new AxisAlignedBB(pos.offset(direction, initialExtensionProgress)); constructCollisionBox = new AxisAlignedBB(BlockPos.ZERO.offset(direction, -initialExtensionProgress));
return true; return true;
} }
@ -125,14 +131,35 @@ public class PistonContraption extends Contraption {
return true; 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); 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 @Override
public void readNBT(CompoundNBT nbt) { public void readNBT(CompoundNBT nbt) {
super.readNBT(nbt); super.readNBT(nbt);
extensionLength = nbt.getInt("ExtensionLength"); extensionLength = nbt.getInt("ExtensionLength");
initialExtensionProgress = nbt.getInt("InitialLength");
orientation = Direction.byIndex(nbt.getInt("Orientation"));
if (nbt.contains("BoundsBack")) if (nbt.contains("BoundsBack"))
pistonCollisionBox = readAABB(nbt.getList("BoundsBack", 5)); pistonCollisionBox = readAABB(nbt.getList("BoundsBack", 5));
} }
@ -145,7 +172,9 @@ public class PistonContraption extends Contraption {
ListNBT bb = writeAABB(pistonCollisionBox); ListNBT bb = writeAABB(pistonCollisionBox);
nbt.put("BoundsBack", bb); nbt.put("BoundsBack", bb);
} }
nbt.putInt("InitialLength", initialExtensionProgress);
nbt.putInt("ExtensionLength", extensionLength); nbt.putInt("ExtensionLength", extensionLength);
nbt.putInt("Orientation", orientation.getIndex());
return nbt; return nbt;
} }