mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-20 01:47:54 +01:00
Tilted Trains
- The collision response now (semi)-supports yaw-pitch combined rotations of contraptions - Attempted collision and rendering of contraption couplings moving up and downhill - Fixed sychronization issues of a mounted contraptions' initial orientation - Contraption couplings no longer render the virtual coupling connection - Entities can no longer mount the cart connected by another carts' contraption - Contraption coupligs no longer rotate backwards when opposite couplings are added onto it - Minecarts no longer deadlock each other when one of them had stalled due to an unloaded coupling end - Cart assemblers only disassemble coupling contraptions if both carts are within an inactive cart assembler - Fixed interactions between coupling contraptions and furnace/chest minecart invs
This commit is contained in:
parent
3956875334
commit
f3deb8ba85
24 changed files with 591 additions and 472 deletions
|
@ -1,6 +1,6 @@
|
||||||
<p align="center"><img src="https://i.imgur.com/35JmqWB.gif" alt="Logo" width="100"></p>
|
<p align="center"><img src="https://i.imgur.com/35JmqWB.gif" alt="Logo" width="100"></p>
|
||||||
<h1 align="center">Create<br>
|
<h1 align="center">Create<br>
|
||||||
<a href="https://www.patreon.com/simibubi"><img src="https://img.shields.io/badge/Supporters-29-ff5733" alt="Patreon"></a>
|
<a href="https://www.patreon.com/simibubi"><img src="https://img.shields.io/badge/Supporters-40-ff5733" alt="Patreon"></a>
|
||||||
<a href="https://www.curseforge.com/minecraft/mc-mods/create/files"><img src="https://img.shields.io/badge/Available%20for-MC%201.14,%201.15-c70039" alt="Supported Versions"></a>
|
<a href="https://www.curseforge.com/minecraft/mc-mods/create/files"><img src="https://img.shields.io/badge/Available%20for-MC%201.14,%201.15-c70039" alt="Supported Versions"></a>
|
||||||
<a href="https://github.com/Creators-of-Create/Create/blob/master/LICENSE"><img src="https://img.shields.io/github/license/Creators-of-Create/Create?style=flat&color=900c3f" alt="License"></a>
|
<a href="https://github.com/Creators-of-Create/Create/blob/master/LICENSE"><img src="https://img.shields.io/github/license/Creators-of-Create/Create?style=flat&color=900c3f" alt="License"></a>
|
||||||
<a href="https://discord.gg/hmaD7Se"><img src="https://img.shields.io/discord/620934202875183104?color=844685&label=Feedback%20%26%20Help&style=flat" alt="Discord"></a>
|
<a href="https://discord.gg/hmaD7Se"><img src="https://img.shields.io/discord/620934202875183104?color=844685&label=Feedback%20%26%20Help&style=flat" alt="Discord"></a>
|
||||||
|
@ -19,7 +19,7 @@ Check out the wiki and in-game Tool-tips for further info on how to use these fe
|
||||||
[<img src="https://i.imgur.com/xj8o2xC.jpg" width="210">](https://www.patreon.com/simibubi "Support Us")
|
[<img src="https://i.imgur.com/xj8o2xC.jpg" width="210">](https://www.patreon.com/simibubi "Support Us")
|
||||||
|
|
||||||
- Support for Minecraft 1.12: Not planned
|
- Support for Minecraft 1.12: Not planned
|
||||||
- Support for Minecraft 1.16: Porting efforts will begin soon.
|
- Support for Minecraft 1.16: Porting efforts are making good progress.
|
||||||
- Support for Fabric: Not planned
|
- Support for Fabric: Not planned
|
||||||
<hr>
|
<hr>
|
||||||
<h4 align="center">Find out more about Create on our <a href="https://www.curseforge.com/minecraft/mc-mods/create">Project Page</a></h4>
|
<h4 align="center">Find out more about Create on our <a href="https://www.curseforge.com/minecraft/mc-mods/create">Project Page</a></h4>
|
||||||
|
|
|
@ -18,8 +18,7 @@ public class BellMovementBehaviour extends MovementBehaviour {
|
||||||
public void onSpeedChanged(MovementContext context, Vec3d oldMotion, Vec3d motion) {
|
public void onSpeedChanged(MovementContext context, Vec3d oldMotion, Vec3d motion) {
|
||||||
double dotProduct = oldMotion.dotProduct(motion);
|
double dotProduct = oldMotion.dotProduct(motion);
|
||||||
|
|
||||||
if (dotProduct <= 0 && (context.relativeMotion.length() != 0 || context.rotation.length() == 0)
|
if (dotProduct <= 0 && (context.relativeMotion.length() != 0) || context.firstMovement)
|
||||||
|| context.firstMovement)
|
|
||||||
context.world.playSound(null, new BlockPos(context.position), SoundEvents.BLOCK_BELL_USE,
|
context.world.playSound(null, new BlockPos(context.position), SoundEvents.BLOCK_BELL_USE,
|
||||||
SoundCategory.BLOCKS, 2.0F, 1.0F);
|
SoundCategory.BLOCKS, 2.0F, 1.0F);
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,7 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour {
|
||||||
private Optional<Direction> getCurrentFacingIfValid(MovementContext context) {
|
private Optional<Direction> getCurrentFacingIfValid(MovementContext context) {
|
||||||
Vec3d directionVec = new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING)
|
Vec3d directionVec = new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING)
|
||||||
.getDirectionVec());
|
.getDirectionVec());
|
||||||
directionVec = VecHelper.rotate(directionVec, context.rotation.x, context.rotation.y, context.rotation.z);
|
directionVec = context.rotation.apply(directionVec);
|
||||||
Direction facingFromVector = Direction.getFacingFromVector(directionVec.x, directionVec.y, directionVec.z);
|
Direction facingFromVector = Direction.getFacingFromVector(directionVec.x, directionVec.y, directionVec.z);
|
||||||
if (directionVec.distanceTo(new Vec3d(facingFromVector.getDirectionVec())) > 1 / 8f)
|
if (directionVec.distanceTo(new Vec3d(facingFromVector.getDirectionVec())) > 1 / 8f)
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
|
|
|
@ -5,7 +5,6 @@ import java.util.HashMap;
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
|
||||||
|
|
||||||
import mcp.MethodsReturnNonnullByDefault;
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
|
@ -63,7 +62,7 @@ public class DispenserMovementBehaviour extends DropperMovementBehaviour {
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3d facingVec = new Vec3d(context.state.get(DispenserBlock.FACING).getDirectionVec());
|
Vec3d facingVec = new Vec3d(context.state.get(DispenserBlock.FACING).getDirectionVec());
|
||||||
facingVec = VecHelper.rotate(facingVec, context.rotation.x, context.rotation.y, context.rotation.z);
|
facingVec = context.rotation.apply(facingVec);
|
||||||
facingVec.normalize();
|
facingVec.normalize();
|
||||||
Direction clostestFacing = Direction.getFacingFromVector(facingVec.x, facingVec.y, facingVec.z);
|
Direction clostestFacing = Direction.getFacingFromVector(facingVec.x, facingVec.y, facingVec.z);
|
||||||
ContraptionBlockSource blockSource = new ContraptionBlockSource(context, pos, clostestFacing);
|
ContraptionBlockSource blockSource = new ContraptionBlockSource(context, pos, clostestFacing);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.simibubi.create.content.contraptions.components.actors.dispenser;
|
package com.simibubi.create.content.contraptions.components.actors.dispenser;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
|
||||||
|
|
||||||
import net.minecraft.block.DispenserBlock;
|
import net.minecraft.block.DispenserBlock;
|
||||||
import net.minecraft.entity.item.ItemEntity;
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
|
@ -37,7 +36,7 @@ public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBeha
|
||||||
@Override
|
@Override
|
||||||
public ItemStack dispense(ItemStack itemStack, MovementContext context, BlockPos pos) {
|
public ItemStack dispense(ItemStack itemStack, MovementContext context, BlockPos pos) {
|
||||||
Vec3d facingVec = new Vec3d(context.state.get(DispenserBlock.FACING).getDirectionVec());
|
Vec3d facingVec = new Vec3d(context.state.get(DispenserBlock.FACING).getDirectionVec());
|
||||||
facingVec = VecHelper.rotate(facingVec, context.rotation.x, context.rotation.y, context.rotation.z);
|
facingVec = context.rotation.apply(facingVec);
|
||||||
facingVec.normalize();
|
facingVec.normalize();
|
||||||
|
|
||||||
Direction closestToFacing = getClosestFacingDirection(facingVec);
|
Direction closestToFacing = getClosestFacingDirection(facingVec);
|
||||||
|
|
|
@ -13,7 +13,6 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov
|
||||||
import com.simibubi.create.content.logistics.item.filter.FilterItem;
|
import com.simibubi.create.content.logistics.item.filter.FilterItem;
|
||||||
import com.simibubi.create.foundation.item.ItemHelper;
|
import com.simibubi.create.foundation.item.ItemHelper;
|
||||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
@ -52,7 +51,7 @@ public class DeployerMovementBehaviour extends MovementBehaviour {
|
||||||
public void activate(MovementContext context, BlockPos pos, DeployerFakePlayer player, Mode mode) {
|
public void activate(MovementContext context, BlockPos pos, DeployerFakePlayer player, Mode mode) {
|
||||||
Vec3d facingVec = new Vec3d(context.state.get(DeployerBlock.FACING)
|
Vec3d facingVec = new Vec3d(context.state.get(DeployerBlock.FACING)
|
||||||
.getDirectionVec());
|
.getDirectionVec());
|
||||||
facingVec = VecHelper.rotate(facingVec, context.rotation.x, context.rotation.y, context.rotation.z);
|
facingVec = context.rotation.apply(facingVec);
|
||||||
Vec3d vec = context.position.subtract(facingVec.scale(2));
|
Vec3d vec = context.position.subtract(facingVec.scale(2));
|
||||||
player.rotationYaw = ContraptionEntity.yawFromVector(facingVec);
|
player.rotationYaw = ContraptionEntity.yawFromVector(facingVec);
|
||||||
player.rotationPitch = ContraptionEntity.pitchFromVector(facingVec) - 90;
|
player.rotationPitch = ContraptionEntity.pitchFromVector(facingVec) - 90;
|
||||||
|
|
|
@ -332,9 +332,14 @@ public abstract class Contraption {
|
||||||
frontier.add(otherPartPos);
|
frontier.add(otherPartPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cart assemblers attach themselves
|
||||||
|
BlockState stateBelow = world.getBlockState(pos.down());
|
||||||
|
if (!visited.contains(pos.down()) && AllBlocks.CART_ASSEMBLER.has(stateBelow))
|
||||||
|
frontier.add(pos.down());
|
||||||
|
|
||||||
Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos);
|
Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos);
|
||||||
|
|
||||||
// Slime blocks drag adjacent blocks if possible
|
// Slime blocks and super glue drag adjacent blocks if possible
|
||||||
boolean isSlimeBlock = state.getBlock() instanceof SlimeBlock;
|
boolean isSlimeBlock = state.getBlock() instanceof SlimeBlock;
|
||||||
for (Direction offset : Direction.values()) {
|
for (Direction offset : Direction.values()) {
|
||||||
BlockPos offsetPos = pos.offset(offset);
|
BlockPos offsetPos = pos.offset(offset);
|
||||||
|
@ -348,16 +353,13 @@ public abstract class Contraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean wasVisited = visited.contains(offsetPos);
|
boolean wasVisited = visited.contains(offsetPos);
|
||||||
boolean isMinecartAssembler = AllBlocks.CART_ASSEMBLER.has(blockState) && offset == Direction.DOWN;
|
|
||||||
boolean faceHasGlue = superglue.containsKey(offset);
|
boolean faceHasGlue = superglue.containsKey(offset);
|
||||||
boolean blockAttachedTowardsFace =
|
boolean blockAttachedTowardsFace =
|
||||||
BlockMovementTraits.isBlockAttachedTowards(blockState, offset.getOpposite());
|
BlockMovementTraits.isBlockAttachedTowards(blockState, offset.getOpposite());
|
||||||
boolean brittle = BlockMovementTraits.isBrittle(blockState);
|
boolean brittle = BlockMovementTraits.isBrittle(blockState);
|
||||||
|
|
||||||
if (!wasVisited
|
if (!wasVisited && ((isSlimeBlock && !brittle) || blockAttachedTowardsFace || faceHasGlue))
|
||||||
&& ((isSlimeBlock && !brittle) || blockAttachedTowardsFace || faceHasGlue || isMinecartAssembler))
|
|
||||||
frontier.add(offsetPos);
|
frontier.add(offsetPos);
|
||||||
|
|
||||||
if (faceHasGlue)
|
if (faceHasGlue)
|
||||||
addGlue(superglue.get(offset));
|
addGlue(superglue.get(offset));
|
||||||
}
|
}
|
||||||
|
@ -763,7 +765,7 @@ public abstract class Contraption {
|
||||||
ctx.position = null;
|
ctx.position = null;
|
||||||
ctx.motion = Vec3d.ZERO;
|
ctx.motion = Vec3d.ZERO;
|
||||||
ctx.relativeMotion = Vec3d.ZERO;
|
ctx.relativeMotion = Vec3d.ZERO;
|
||||||
ctx.rotation = Vec3d.ZERO;
|
ctx.rotation = v -> v;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.Direction.AxisDirection;
|
import net.minecraft.util.Direction.AxisDirection;
|
||||||
import net.minecraft.util.ReuseableStream;
|
import net.minecraft.util.ReuseableStream;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
|
@ -71,8 +72,18 @@ public class ContraptionCollider {
|
||||||
|
|
||||||
Vec3d centerOfBlock = VecHelper.getCenterOf(BlockPos.ZERO);
|
Vec3d centerOfBlock = VecHelper.getCenterOf(BlockPos.ZERO);
|
||||||
double conRotX = contraptionRotation.x;
|
double conRotX = contraptionRotation.x;
|
||||||
double conRotY = contraptionRotation.y;
|
double conRotY = contraptionRotation.y + contraptionEntity.getInitialYaw();
|
||||||
double conRotZ = contraptionRotation.z;
|
double conRotZ = contraptionRotation.z;
|
||||||
|
|
||||||
|
double reverseYaw = 0;
|
||||||
|
|
||||||
|
// Collision algorithm does not support rotation around two axes -> rotate
|
||||||
|
// entities manually
|
||||||
|
if (conRotZ != 0 && contraptionRotation.y != 0) {
|
||||||
|
reverseYaw = contraptionRotation.y;
|
||||||
|
conRotY = contraptionEntity.getInitialYaw();
|
||||||
|
}
|
||||||
|
|
||||||
Vec3d contraptionCentreOffset = contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0);
|
Vec3d contraptionCentreOffset = contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0);
|
||||||
boolean axisAlignedCollision = contraptionRotation.equals(Vec3d.ZERO);
|
boolean axisAlignedCollision = contraptionRotation.equals(Vec3d.ZERO);
|
||||||
Matrix3d rotation = null;
|
Matrix3d rotation = null;
|
||||||
|
@ -100,13 +111,15 @@ public class ContraptionCollider {
|
||||||
Vec3d centerY = new Vec3d(0, entityBounds.getYSize() / 2, 0);
|
Vec3d centerY = new Vec3d(0, entityBounds.getYSize() / 2, 0);
|
||||||
Vec3d motion = entity.getMotion();
|
Vec3d motion = entity.getMotion();
|
||||||
|
|
||||||
Vec3d position = entityPosition.subtract(contraptionCentreOffset)
|
Vec3d position = entityPosition;
|
||||||
.add(centerY);
|
position = position.subtract(contraptionCentreOffset);
|
||||||
|
position = position.add(centerY);
|
||||||
position = position.subtract(contraptionPosition);
|
position = position.subtract(contraptionPosition);
|
||||||
|
position = VecHelper.rotate(position, -reverseYaw, Axis.Y);
|
||||||
position = rotation.transform(position);
|
position = rotation.transform(position);
|
||||||
position = position.add(centerOfBlock)
|
position = position.add(centerOfBlock);
|
||||||
.subtract(centerY)
|
position = position.subtract(centerY);
|
||||||
.subtract(entityPosition);
|
position = position.subtract(entityPosition);
|
||||||
|
|
||||||
// Find all potential block shapes to collide with
|
// Find all potential block shapes to collide with
|
||||||
AxisAlignedBB localBB = entityBounds.offset(position)
|
AxisAlignedBB localBB = entityBounds.offset(position)
|
||||||
|
@ -187,10 +200,12 @@ public class ContraptionCollider {
|
||||||
Vec3d motionResponse = allowedMotion.getValue();
|
Vec3d motionResponse = allowedMotion.getValue();
|
||||||
boolean hardCollision = !totalResponse.equals(Vec3d.ZERO);
|
boolean hardCollision = !totalResponse.equals(Vec3d.ZERO);
|
||||||
|
|
||||||
|
|
||||||
rotation.transpose();
|
rotation.transpose();
|
||||||
motionResponse = rotation.transform(motionResponse)
|
motionResponse = rotation.transform(motionResponse)
|
||||||
.add(contraptionMotion);
|
.add(contraptionMotion);
|
||||||
totalResponse = rotation.transform(totalResponse);
|
totalResponse = rotation.transform(totalResponse);
|
||||||
|
totalResponse = VecHelper.rotate(totalResponse, reverseYaw, Axis.Y);
|
||||||
rotation.transpose();
|
rotation.transpose();
|
||||||
|
|
||||||
if (futureCollision.isTrue() && playerType != PlayerType.SERVER) {
|
if (futureCollision.isTrue() && playerType != PlayerType.SERVER) {
|
||||||
|
@ -235,6 +250,7 @@ public class ContraptionCollider {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
totalResponse = totalResponse.add(contactPointMotion);
|
totalResponse = totalResponse.add(contactPointMotion);
|
||||||
Vec3d allowedMovement = getAllowedMovement(totalResponse, entity);
|
Vec3d allowedMovement = getAllowedMovement(totalResponse, entity);
|
||||||
contraptionEntity.collidingEntities.add(entity);
|
contraptionEntity.collidingEntities.add(entity);
|
||||||
|
|
|
@ -25,6 +25,8 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra
|
||||||
import com.simibubi.create.foundation.item.ItemHelper;
|
import com.simibubi.create.foundation.item.ItemHelper;
|
||||||
import com.simibubi.create.foundation.networking.AllPackets;
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -33,7 +35,6 @@ import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.IProjectile;
|
import net.minecraft.entity.IProjectile;
|
||||||
import net.minecraft.entity.item.BoatEntity;
|
|
||||||
import net.minecraft.entity.item.HangingEntity;
|
import net.minecraft.entity.item.HangingEntity;
|
||||||
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
import net.minecraft.entity.item.minecart.FurnaceMinecartEntity;
|
import net.minecraft.entity.item.minecart.FurnaceMinecartEntity;
|
||||||
|
@ -49,10 +50,12 @@ import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraft.network.datasync.DataParameter;
|
import net.minecraft.network.datasync.DataParameter;
|
||||||
import net.minecraft.network.datasync.DataSerializers;
|
import net.minecraft.network.datasync.DataSerializers;
|
||||||
import net.minecraft.network.datasync.EntityDataManager;
|
import net.minecraft.network.datasync.EntityDataManager;
|
||||||
|
import net.minecraft.network.datasync.IDataSerializer;
|
||||||
import net.minecraft.tags.BlockTags;
|
import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.DamageSource;
|
import net.minecraft.util.DamageSource;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
@ -69,26 +72,48 @@ import net.minecraftforge.fml.network.PacketDistributor;
|
||||||
|
|
||||||
public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnData {
|
public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnData {
|
||||||
|
|
||||||
|
public static final IDataSerializer<Optional<Direction>> OPTIONAL_DIRECTION =
|
||||||
|
new IDataSerializer<Optional<Direction>>() {
|
||||||
|
|
||||||
|
public void write(PacketBuffer buffer, Optional<Direction> opt) {
|
||||||
|
buffer.writeVarInt(opt.map(Direction::ordinal)
|
||||||
|
.orElse(-1) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Direction> read(PacketBuffer buffer) {
|
||||||
|
int i = buffer.readVarInt();
|
||||||
|
return i == 0 ? Optional.empty() : Optional.of(Direction.values()[i - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Direction> copyValue(Optional<Direction> opt) {
|
||||||
|
return Optional.ofNullable(opt.orElse(null));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static {
|
||||||
|
DataSerializers.registerSerializer(OPTIONAL_DIRECTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Entity> collidingEntities = new ArrayList<>();
|
||||||
|
|
||||||
protected Contraption contraption;
|
protected Contraption contraption;
|
||||||
protected float initialAngle;
|
|
||||||
protected float forcedAngle;
|
|
||||||
protected BlockPos controllerPos;
|
protected BlockPos controllerPos;
|
||||||
protected Vec3d motionBeforeStall;
|
protected Vec3d motionBeforeStall;
|
||||||
|
protected boolean forceAngle;
|
||||||
protected boolean stationary;
|
protected boolean stationary;
|
||||||
protected boolean initialized;
|
protected boolean initialized;
|
||||||
final List<Entity> collidingEntities = new ArrayList<>();
|
|
||||||
private boolean isSerializingFurnaceCart;
|
private boolean isSerializingFurnaceCart;
|
||||||
private boolean attachedExtraInventories;
|
private boolean attachedExtraInventories;
|
||||||
private boolean prevPosInvalid;
|
private boolean prevPosInvalid;
|
||||||
|
|
||||||
private static final Ingredient FUEL_ITEMS = Ingredient.fromItems(Items.COAL, Items.CHARCOAL);
|
private static final Ingredient FUEL_ITEMS = Ingredient.fromItems(Items.COAL, Items.CHARCOAL);
|
||||||
|
|
||||||
private static final DataParameter<Boolean> STALLED =
|
private static final DataParameter<Boolean> STALLED =
|
||||||
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN);
|
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN);
|
||||||
|
|
||||||
private static final DataParameter<Optional<UUID>> COUPLING =
|
private static final DataParameter<Optional<UUID>> COUPLING =
|
||||||
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.OPTIONAL_UNIQUE_ID);
|
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.OPTIONAL_UNIQUE_ID);
|
||||||
private static final DataParameter<Optional<UUID>> COUPLED_CART =
|
private static final DataParameter<Optional<Direction>> INITIAL_ORIENTATION =
|
||||||
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.OPTIONAL_UNIQUE_ID);
|
EntityDataManager.createKey(ContraptionEntity.class, ContraptionEntity.OPTIONAL_DIRECTION);
|
||||||
|
|
||||||
public float prevYaw;
|
public float prevYaw;
|
||||||
public float prevPitch;
|
public float prevPitch;
|
||||||
|
@ -108,23 +133,15 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
stationary = entityTypeIn == AllEntityTypes.STATIONARY_CONTRAPTION.get();
|
stationary = entityTypeIn == AllEntityTypes.STATIONARY_CONTRAPTION.get();
|
||||||
isSerializingFurnaceCart = false;
|
isSerializingFurnaceCart = false;
|
||||||
attachedExtraInventories = false;
|
attachedExtraInventories = false;
|
||||||
forcedAngle = -1;
|
|
||||||
prevPosInvalid = true;
|
prevPosInvalid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle) {
|
public static ContraptionEntity createMounted(World world, Contraption contraption,
|
||||||
|
Optional<Direction> initialOrientation) {
|
||||||
ContraptionEntity entity = new ContraptionEntity(AllEntityTypes.CONTRAPTION.get(), world);
|
ContraptionEntity entity = new ContraptionEntity(AllEntityTypes.CONTRAPTION.get(), world);
|
||||||
entity.contraptionCreated(contraption);
|
entity.contraptionCreated(contraption);
|
||||||
entity.initialAngle = initialAngle;
|
initialOrientation.ifPresent(entity::setInitialOrientation);
|
||||||
entity.forceYaw(initialAngle);
|
entity.startAtInitialYaw();
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle,
|
|
||||||
Direction facing) {
|
|
||||||
ContraptionEntity entity = createMounted(world, contraption, initialAngle);
|
|
||||||
entity.forcedAngle = facing.getHorizontalAngle();
|
|
||||||
entity.forceYaw(entity.forcedAngle);
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +151,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reOrientate(Direction newInitialAngle) {
|
||||||
|
setInitialOrientation(newInitialAngle);
|
||||||
|
}
|
||||||
|
|
||||||
protected void contraptionCreated(Contraption contraption) {
|
protected void contraptionCreated(Contraption contraption) {
|
||||||
this.contraption = contraption;
|
this.contraption = contraption;
|
||||||
if (contraption == null)
|
if (contraption == null)
|
||||||
|
@ -220,7 +241,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
BlockPos seat = contraption.getSeat(passenger.getUniqueID());
|
BlockPos seat = contraption.getSeat(passenger.getUniqueID());
|
||||||
if (seat == null)
|
if (seat == null)
|
||||||
return null;
|
return null;
|
||||||
Vec3d transformedVector = toGlobalVector(new Vec3d(seat).add(.5, passenger.getYOffset() + ySize - .15f, .5))
|
Vec3d transformedVector = toGlobalVector(new Vec3d(seat).add(.5, passenger.getYOffset() + ySize - .15f, .5), 1)
|
||||||
.add(VecHelper.getCenterOf(BlockPos.ZERO))
|
.add(VecHelper.getCenterOf(BlockPos.ZERO))
|
||||||
.subtract(0.5, ySize, 0.5);
|
.subtract(0.5, ySize, 0.5);
|
||||||
return transformedVector;
|
return transformedVector;
|
||||||
|
@ -268,20 +289,20 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vec3d toGlobalVector(Vec3d localVec) {
|
public Vec3d toGlobalVector(Vec3d localVec, float partialTicks) {
|
||||||
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
||||||
localVec = localVec.subtract(rotationOffset);
|
localVec = localVec.subtract(rotationOffset);
|
||||||
localVec = VecHelper.rotate(localVec, getRotationVec());
|
localVec = applyRotation(localVec, partialTicks);
|
||||||
localVec = localVec.add(rotationOffset)
|
localVec = localVec.add(rotationOffset)
|
||||||
.add(getAnchorVec());
|
.add(getAnchorVec());
|
||||||
return localVec;
|
return localVec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vec3d toLocalVector(Vec3d globalVec) {
|
public Vec3d toLocalVector(Vec3d globalVec, float partialTicks) {
|
||||||
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
||||||
globalVec = globalVec.subtract(getAnchorVec())
|
globalVec = globalVec.subtract(getAnchorVec())
|
||||||
.subtract(rotationOffset);
|
.subtract(rotationOffset);
|
||||||
globalVec = VecHelper.rotate(globalVec, getRotationVec().scale(-1));
|
globalVec = reverseRotation(globalVec, partialTicks);
|
||||||
globalVec = globalVec.add(rotationOffset);
|
globalVec = globalVec.add(rotationOffset);
|
||||||
return globalVec;
|
return globalVec;
|
||||||
}
|
}
|
||||||
|
@ -311,7 +332,6 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
|
|
||||||
if (getMotion().length() < 1 / 4098f)
|
if (getMotion().length() < 1 / 4098f)
|
||||||
setMotion(Vec3d.ZERO);
|
setMotion(Vec3d.ZERO);
|
||||||
|
|
||||||
move(getMotion().x, getMotion().y, getMotion().z);
|
move(getMotion().x, getMotion().y, getMotion().z);
|
||||||
if (ContraptionCollider.collideBlocks(this))
|
if (ContraptionCollider.collideBlocks(this))
|
||||||
getController().collided();
|
getController().collided();
|
||||||
|
@ -323,6 +343,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
prevRoll = roll;
|
prevRoll = roll;
|
||||||
|
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tickAsPassenger(Entity e) {
|
public void tickAsPassenger(Entity e) {
|
||||||
|
@ -330,51 +351,68 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
boolean pauseWhileRotating = false;
|
boolean pauseWhileRotating = false;
|
||||||
boolean rotating = false;
|
boolean rotating = false;
|
||||||
boolean wasStalled = isStalled();
|
boolean wasStalled = isStalled();
|
||||||
|
|
||||||
Entity riding = e;
|
|
||||||
while (riding.getRidingEntity() != null)
|
|
||||||
riding = riding.getRidingEntity();
|
|
||||||
if (!attachedExtraInventories) {
|
|
||||||
contraption.addExtraInventories(riding);
|
|
||||||
attachedExtraInventories = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contraption instanceof MountedContraption) {
|
if (contraption instanceof MountedContraption) {
|
||||||
MountedContraption mountedContraption = (MountedContraption) contraption;
|
MountedContraption mountedContraption = (MountedContraption) contraption;
|
||||||
rotationLock = mountedContraption.rotationMode == CartMovementMode.ROTATION_LOCKED;
|
rotationLock = mountedContraption.rotationMode == CartMovementMode.ROTATION_LOCKED;
|
||||||
pauseWhileRotating = mountedContraption.rotationMode == CartMovementMode.ROTATE_PAUSED;
|
pauseWhileRotating = mountedContraption.rotationMode == CartMovementMode.ROTATE_PAUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Entity riding = e;
|
||||||
|
while (riding.getRidingEntity() != null)
|
||||||
|
riding = riding.getRidingEntity();
|
||||||
|
|
||||||
boolean isOnCoupling = false;
|
boolean isOnCoupling = false;
|
||||||
UUID couplingId = getCouplingId();
|
UUID couplingId = getCouplingId();
|
||||||
isOnCoupling = couplingId != null && riding instanceof AbstractMinecartEntity;
|
isOnCoupling = couplingId != null && riding instanceof AbstractMinecartEntity;
|
||||||
|
|
||||||
|
if (!attachedExtraInventories) {
|
||||||
|
attachInventoriesFromRidingCarts(riding, isOnCoupling, couplingId);
|
||||||
|
attachedExtraInventories = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (isOnCoupling) {
|
if (isOnCoupling) {
|
||||||
// MinecartCoupling coupling = MinecartCouplingHandler.getCoupling(world, couplingId);
|
Couple<MinecartController> coupledCarts = getCoupledCartsIfPresent();
|
||||||
// if (coupling != null && coupling.areBothEndsPresent()) {
|
if (coupledCarts != null) {
|
||||||
// boolean notOnMainCart = !coupling.getId()
|
|
||||||
// .equals(riding.getUniqueID());
|
Vec3d positionVec = coupledCarts.getFirst()
|
||||||
// Vec3d positionVec = coupling.asCouple()
|
.cart()
|
||||||
// .get(notOnMainCart)
|
.getPositionVec();
|
||||||
// .getPositionVec();
|
Vec3d coupledVec = coupledCarts.getSecond()
|
||||||
// prevYaw = yaw;
|
.cart()
|
||||||
// prevPitch = pitch;
|
.getPositionVec();
|
||||||
// double diffZ = positionVec.z - riding.getZ();
|
|
||||||
// double diffX = positionVec.x - riding.getX();
|
double diffX = positionVec.x - coupledVec.x;
|
||||||
// yaw = (float) (MathHelper.atan2(diffZ, diffX) * 180 / Math.PI);
|
double diffY = positionVec.y - coupledVec.y;
|
||||||
// pitch = (float) (Math.atan2(positionVec.y - getY(), Math.sqrt(diffX * diffX + diffZ * diffZ)) * 180
|
double diffZ = positionVec.z - coupledVec.z;
|
||||||
// / Math.PI);
|
|
||||||
//
|
prevYaw = yaw;
|
||||||
// if (notOnMainCart) {
|
prevPitch = pitch;
|
||||||
// yaw += 180;
|
yaw = (float) (MathHelper.atan2(diffZ, diffX) * 180 / Math.PI);
|
||||||
// }
|
pitch = (float) (Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ)) * 180 / Math.PI);
|
||||||
// }
|
|
||||||
|
if (couplingId.equals(riding.getUniqueID())) {
|
||||||
|
pitch *= -1;
|
||||||
|
yaw += 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} else if (!wasStalled) {
|
} else if (!wasStalled) {
|
||||||
Vec3d movementVector = riding.getMotion();
|
Vec3d movementVector = riding.getMotion();
|
||||||
if (riding instanceof BoatEntity)
|
if (!(riding instanceof AbstractMinecartEntity))
|
||||||
movementVector = getPositionVec().subtract(prevPosX, prevPosY, prevPosZ);
|
movementVector = getPositionVec().subtract(prevPosX, prevPosY, prevPosZ);
|
||||||
Vec3d motion = movementVector.normalize();
|
Vec3d motion = movementVector.normalize();
|
||||||
|
|
||||||
|
if (!dataManager.get(INITIAL_ORIENTATION)
|
||||||
|
.isPresent() && !world.isRemote) {
|
||||||
|
if (motion.length() > 0) {
|
||||||
|
Direction facingFromVector = Direction.getFacingFromVector(motion.x, motion.y, motion.z);
|
||||||
|
if (facingFromVector.getAxis()
|
||||||
|
.isHorizontal())
|
||||||
|
setInitialOrientation(facingFromVector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!rotationLock) {
|
if (!rotationLock) {
|
||||||
if (motion.length() > 0) {
|
if (motion.length() > 0) {
|
||||||
targetYaw = yawFromVector(motion);
|
targetYaw = yawFromVector(motion);
|
||||||
|
@ -415,7 +453,25 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isStalled() && (riding instanceof FurnaceMinecartEntity)) {
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!isStalled()) {
|
||||||
|
if (isOnCoupling) {
|
||||||
|
Couple<MinecartController> coupledCarts = getCoupledCartsIfPresent();
|
||||||
|
if (coupledCarts == null)
|
||||||
|
return;
|
||||||
|
coupledCarts.map(MinecartController::cart)
|
||||||
|
.forEach(this::powerFurnaceCartWithFuelFromStorage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
powerFurnaceCartWithFuelFromStorage(riding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void powerFurnaceCartWithFuelFromStorage(Entity riding) {
|
||||||
|
if (!(riding instanceof FurnaceMinecartEntity))
|
||||||
|
return;
|
||||||
FurnaceMinecartEntity furnaceCart = (FurnaceMinecartEntity) riding;
|
FurnaceMinecartEntity furnaceCart = (FurnaceMinecartEntity) riding;
|
||||||
|
|
||||||
// Notify to not trigger serialization side-effects
|
// Notify to not trigger serialization side-effects
|
||||||
|
@ -455,12 +511,51 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
furnaceCart.deserializeNBT(nbt);
|
furnaceCart.deserializeNBT(nbt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Couple<MinecartController> getCoupledCartsIfPresent() {
|
||||||
|
UUID couplingId = getCouplingId();
|
||||||
|
if (couplingId == null)
|
||||||
|
return null;
|
||||||
|
MinecartController controller = CapabilityMinecartController.getIfPresent(world, couplingId);
|
||||||
|
if (controller == null || !controller.isPresent())
|
||||||
|
return null;
|
||||||
|
UUID coupledCart = controller.getCoupledCart(true);
|
||||||
|
MinecartController coupledController = CapabilityMinecartController.getIfPresent(world, coupledCart);
|
||||||
|
if (coupledController == null || !coupledController.isPresent())
|
||||||
|
return null;
|
||||||
|
return Couple.create(controller, coupledController);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void attachInventoriesFromRidingCarts(Entity riding, boolean isOnCoupling, UUID couplingId) {
|
||||||
|
if (isOnCoupling) {
|
||||||
|
Couple<MinecartController> coupledCarts = getCoupledCartsIfPresent();
|
||||||
|
if (coupledCarts == null)
|
||||||
|
return;
|
||||||
|
coupledCarts.map(MinecartController::cart)
|
||||||
|
.forEach(contraption::addExtraInventories);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
contraption.addExtraInventories(riding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3d applyRotation(Vec3d localPos, float partialTicks) {
|
||||||
|
localPos = VecHelper.rotate(localPos, getRoll(partialTicks), Axis.X);
|
||||||
|
localPos = VecHelper.rotate(localPos, getInitialYaw(), Axis.Y);
|
||||||
|
localPos = VecHelper.rotate(localPos, getPitch(partialTicks), Axis.Z);
|
||||||
|
localPos = VecHelper.rotate(localPos, getYaw(partialTicks), Axis.Y);
|
||||||
|
return localPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3d reverseRotation(Vec3d localPos, float partialTicks) {
|
||||||
|
localPos = VecHelper.rotate(localPos, -getYaw(partialTicks), Axis.Y);
|
||||||
|
localPos = VecHelper.rotate(localPos, -getPitch(partialTicks), Axis.Z);
|
||||||
|
localPos = VecHelper.rotate(localPos, -getInitialYaw(), Axis.Y);
|
||||||
|
localPos = VecHelper.rotate(localPos, -getRoll(partialTicks), Axis.X);
|
||||||
|
return localPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tickActors() {
|
public void tickActors() {
|
||||||
Vec3d rotationVec = getRotationVec();
|
|
||||||
Vec3d reversedRotationVec = rotationVec.scale(-1);
|
|
||||||
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
|
||||||
boolean stalledPreviously = contraption.stalled;
|
boolean stalledPreviously = contraption.stalled;
|
||||||
|
|
||||||
if (!world.isRemote)
|
if (!world.isRemote)
|
||||||
|
@ -471,12 +566,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
BlockInfo blockInfo = pair.left;
|
BlockInfo blockInfo = pair.left;
|
||||||
MovementBehaviour actor = Contraption.getMovement(blockInfo.state);
|
MovementBehaviour actor = Contraption.getMovement(blockInfo.state);
|
||||||
|
|
||||||
Vec3d actorPosition = new Vec3d(blockInfo.pos);
|
Vec3d actorPosition = toGlobalVector(VecHelper.getCenterOf(blockInfo.pos)
|
||||||
actorPosition = actorPosition.add(actor.getActiveAreaOffset(context));
|
.add(actor.getActiveAreaOffset(context)), 1);
|
||||||
actorPosition = VecHelper.rotate(actorPosition, rotationVec);
|
|
||||||
actorPosition = actorPosition.add(rotationOffset)
|
|
||||||
.add(getAnchorVec());
|
|
||||||
|
|
||||||
boolean newPosVisited = false;
|
boolean newPosVisited = false;
|
||||||
BlockPos gridPosition = new BlockPos(actorPosition);
|
BlockPos gridPosition = new BlockPos(actorPosition);
|
||||||
Vec3d oldMotion = context.motion;
|
Vec3d oldMotion = context.motion;
|
||||||
|
@ -486,7 +577,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
if (previousPosition != null) {
|
if (previousPosition != null) {
|
||||||
context.motion = actorPosition.subtract(previousPosition);
|
context.motion = actorPosition.subtract(previousPosition);
|
||||||
Vec3d relativeMotion = context.motion;
|
Vec3d relativeMotion = context.motion;
|
||||||
relativeMotion = VecHelper.rotate(relativeMotion, reversedRotationVec);
|
relativeMotion = reverseRotation(relativeMotion, 1);
|
||||||
context.relativeMotion = relativeMotion;
|
context.relativeMotion = relativeMotion;
|
||||||
newPosVisited = !new BlockPos(previousPosition).equals(gridPosition)
|
newPosVisited = !new BlockPos(previousPosition).equals(gridPosition)
|
||||||
|| context.relativeMotion.length() > 0 && context.firstMovement;
|
|| context.relativeMotion.length() > 0 && context.firstMovement;
|
||||||
|
@ -514,7 +605,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.rotation = rotationVec;
|
context.rotation = v -> applyRotation(v, 1);
|
||||||
context.position = actorPosition;
|
context.position = actorPosition;
|
||||||
|
|
||||||
if (actor.isActive(context)) {
|
if (actor.isActive(context)) {
|
||||||
|
@ -561,6 +652,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
@Override
|
@Override
|
||||||
public void notifyDataManagerChange(DataParameter<?> key) {
|
public void notifyDataManagerChange(DataParameter<?> key) {
|
||||||
super.notifyDataManagerChange(key);
|
super.notifyDataManagerChange(key);
|
||||||
|
if (key == INITIAL_ORIENTATION)
|
||||||
|
startAtInitialYaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rotate(double roll, double yaw, double pitch) {
|
public void rotate(double roll, double yaw, double pitch) {
|
||||||
|
@ -599,7 +692,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
|
|
||||||
public float getYaw(float partialTicks) {
|
public float getYaw(float partialTicks) {
|
||||||
return (getRidingEntity() == null ? 1 : -1)
|
return (getRidingEntity() == null ? 1 : -1)
|
||||||
* (partialTicks == 1.0F ? yaw : angleLerp(partialTicks, prevYaw, yaw)) + initialAngle;
|
* (partialTicks == 1.0F ? yaw : angleLerp(partialTicks, prevYaw, yaw));
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getPitch(float partialTicks) {
|
public float getPitch(float partialTicks) {
|
||||||
|
@ -620,16 +713,20 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
protected void registerData() {
|
protected void registerData() {
|
||||||
this.dataManager.register(STALLED, false);
|
this.dataManager.register(STALLED, false);
|
||||||
this.dataManager.register(COUPLING, Optional.empty());
|
this.dataManager.register(COUPLING, Optional.empty());
|
||||||
this.dataManager.register(COUPLED_CART, Optional.empty());
|
this.dataManager.register(INITIAL_ORIENTATION, Optional.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void readAdditional(CompoundNBT compound) {
|
protected void readAdditional(CompoundNBT compound) {
|
||||||
initialized = compound.getBoolean("Initialized");
|
initialized = compound.getBoolean("Initialized");
|
||||||
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
|
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
|
||||||
initialAngle = compound.getFloat("InitialAngle");
|
|
||||||
forceYaw(compound.contains("ForcedYaw") ? compound.getFloat("ForcedYaw") : initialAngle);
|
|
||||||
dataManager.set(STALLED, compound.getBoolean("Stalled"));
|
dataManager.set(STALLED, compound.getBoolean("Stalled"));
|
||||||
|
|
||||||
|
if (compound.contains("InitialOrientation"))
|
||||||
|
setInitialOrientation(NBTHelper.readEnum(compound, "InitialOrientation", Direction.class));
|
||||||
|
if (compound.contains("ForceYaw"))
|
||||||
|
startAtYaw(compound.getFloat("ForceYaw"));
|
||||||
|
|
||||||
ListNBT vecNBT = compound.getList("CachedMotion", 6);
|
ListNBT vecNBT = compound.getList("CachedMotion", 6);
|
||||||
if (!vecNBT.isEmpty()) {
|
if (!vecNBT.isEmpty()) {
|
||||||
motionBeforeStall = new Vec3d(vecNBT.getDouble(0), vecNBT.getDouble(1), vecNBT.getDouble(2));
|
motionBeforeStall = new Vec3d(vecNBT.getDouble(0), vecNBT.getDouble(1), vecNBT.getDouble(2));
|
||||||
|
@ -637,20 +734,20 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
targetYaw = prevYaw = yaw += yawFromVector(motionBeforeStall);
|
targetYaw = prevYaw = yaw += yawFromVector(motionBeforeStall);
|
||||||
setMotion(Vec3d.ZERO);
|
setMotion(Vec3d.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compound.contains("Controller"))
|
if (compound.contains("Controller"))
|
||||||
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
|
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
|
||||||
|
setCouplingId(
|
||||||
if (compound.contains("OnCoupling")) {
|
compound.contains("OnCoupling") ? NBTUtil.readUniqueId(compound.getCompound("OnCoupling")) : null);
|
||||||
setCouplingId(NBTUtil.readUniqueId(compound.getCompound("OnCoupling")));
|
|
||||||
setCoupledCart(NBTUtil.readUniqueId(compound.getCompound("CoupledCart")));
|
|
||||||
} else {
|
|
||||||
setCouplingId(null);
|
|
||||||
setCoupledCart(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forceYaw(float forcedYaw) {
|
public void startAtInitialYaw() {
|
||||||
targetYaw = yaw = prevYaw = forcedYaw;
|
startAtYaw(getInitialYaw());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startAtYaw(float yaw) {
|
||||||
|
targetYaw = this.yaw = prevYaw = yaw;
|
||||||
|
forceAngle = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkController() {
|
public void checkController() {
|
||||||
|
@ -679,17 +776,20 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z));
|
newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z));
|
||||||
if (controllerPos != null)
|
if (controllerPos != null)
|
||||||
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
|
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
|
||||||
if (forcedAngle != -1)
|
|
||||||
compound.putFloat("ForcedYaw", forcedAngle);
|
|
||||||
|
|
||||||
compound.putFloat("InitialAngle", initialAngle);
|
Optional<Direction> optional = dataManager.get(INITIAL_ORIENTATION);
|
||||||
|
if (optional.isPresent())
|
||||||
|
NBTHelper.writeEnum(compound, "InitialOrientation", optional.get());
|
||||||
|
if (forceAngle) {
|
||||||
|
compound.putFloat("ForceYaw", yaw);
|
||||||
|
forceAngle = false;
|
||||||
|
}
|
||||||
|
|
||||||
compound.putBoolean("Stalled", isStalled());
|
compound.putBoolean("Stalled", isStalled());
|
||||||
compound.putBoolean("Initialized", initialized);
|
compound.putBoolean("Initialized", initialized);
|
||||||
|
|
||||||
if (getCouplingId() != null) {
|
if (getCouplingId() != null)
|
||||||
compound.put("OnCoupling", NBTUtil.writeUniqueId(getCouplingId()));
|
compound.put("OnCoupling", NBTUtil.writeUniqueId(getCouplingId()));
|
||||||
compound.put("CoupledCart", NBTUtil.writeUniqueId(getCoupledCart()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -715,7 +815,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
if (getContraption() != null) {
|
if (getContraption() != null) {
|
||||||
remove();
|
remove();
|
||||||
BlockPos offset = new BlockPos(getAnchorVec().add(.5, .5, .5));
|
BlockPos offset = new BlockPos(getAnchorVec().add(.5, .5, .5));
|
||||||
Vec3d rotation = getRotationVec();
|
Vec3d rotation = getRotationVec().add(0, getInitialYaw(), 0);
|
||||||
StructureTransform transform = new StructureTransform(offset, rotation);
|
StructureTransform transform = new StructureTransform(offset, rotation);
|
||||||
contraption.addBlocksToWorld(world, transform);
|
contraption.addBlocksToWorld(world, transform);
|
||||||
contraption.addPassengersToWorld(world, transform, getPassengers());
|
contraption.addPassengersToWorld(world, transform, getPassengers());
|
||||||
|
@ -725,7 +825,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
Vec3d positionVec = getPositionVec();
|
Vec3d positionVec = getPositionVec();
|
||||||
Vec3d localVec = entity.getPositionVec()
|
Vec3d localVec = entity.getPositionVec()
|
||||||
.subtract(positionVec);
|
.subtract(positionVec);
|
||||||
localVec = VecHelper.rotate(localVec, getRotationVec().scale(-1));
|
localVec = VecHelper.rotate(localVec, rotation.scale(-1));
|
||||||
Vec3d transformed = transform.apply(localVec);
|
Vec3d transformed = transform.apply(localVec);
|
||||||
entity.setPositionAndUpdate(transformed.x, transformed.y, transformed.z);
|
entity.setPositionAndUpdate(transformed.x, transformed.y, transformed.z);
|
||||||
}
|
}
|
||||||
|
@ -844,8 +944,18 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getInitialAngle() {
|
public void setInitialOrientation(Direction direction) {
|
||||||
return initialAngle;
|
dataManager.set(INITIAL_ORIENTATION, Optional.of(direction));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Direction> getInitialOrientation() {
|
||||||
|
return dataManager.get(INITIAL_ORIENTATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getInitialYaw() {
|
||||||
|
return dataManager.get(INITIAL_ORIENTATION)
|
||||||
|
.orElse(Direction.SOUTH)
|
||||||
|
.getHorizontalAngle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vec3d getRotationVec() {
|
public Vec3d getRotationVec() {
|
||||||
|
@ -863,18 +973,9 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
public Vec3d getContactPointMotion(Vec3d globalContactPoint) {
|
public Vec3d getContactPointMotion(Vec3d globalContactPoint) {
|
||||||
if (prevPosInvalid)
|
if (prevPosInvalid)
|
||||||
return Vec3d.ZERO;
|
return Vec3d.ZERO;
|
||||||
|
Vec3d contactPoint = toGlobalVector(toLocalVector(globalContactPoint, 0), 1);
|
||||||
Vec3d positionVec = getPositionVec();
|
return contactPoint.subtract(globalContactPoint)
|
||||||
Vec3d conMotion = positionVec.subtract(getPrevPositionVec());
|
.add(getPositionVec().subtract(getPrevPositionVec()));
|
||||||
Vec3d conAngularMotion = getRotationVec().subtract(getPrevRotationVec());
|
|
||||||
Vec3d contraptionCentreOffset = stationary ? VecHelper.getCenterOf(BlockPos.ZERO) : Vec3d.ZERO.add(0, 0.5, 0);
|
|
||||||
Vec3d contactPoint = globalContactPoint.subtract(contraptionCentreOffset)
|
|
||||||
.subtract(positionVec);
|
|
||||||
contactPoint = VecHelper.rotate(contactPoint, conAngularMotion.x, conAngularMotion.y, conAngularMotion.z);
|
|
||||||
contactPoint = contactPoint.add(positionVec)
|
|
||||||
.add(contraptionCentreOffset)
|
|
||||||
.add(conMotion);
|
|
||||||
return contactPoint.subtract(globalContactPoint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canCollideWith(Entity e) {
|
public boolean canCollideWith(Entity e) {
|
||||||
|
@ -915,16 +1016,6 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
dataManager.set(COUPLING, Optional.ofNullable(id));
|
dataManager.set(COUPLING, Optional.ofNullable(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public UUID getCoupledCart() {
|
|
||||||
Optional<UUID> uuid = dataManager.get(COUPLED_CART);
|
|
||||||
return uuid.isPresent() ? uuid.get() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCoupledCart(UUID id) {
|
|
||||||
dataManager.set(COUPLED_CART, Optional.ofNullable(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOnePlayerRiding() {
|
public boolean isOnePlayerRiding() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -39,13 +39,10 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
|
||||||
MatrixStack msLocal = getLocalTransform(entity);
|
MatrixStack msLocal = getLocalTransform(entity);
|
||||||
MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal };
|
MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal };
|
||||||
|
|
||||||
float degYaw = entity.getYaw(partialTicks);
|
float angleInitialYaw = entity.getInitialYaw();
|
||||||
float degPitch = entity.getPitch(partialTicks);
|
float angleYaw = entity.getYaw(partialTicks);
|
||||||
float degRoll = entity.getRoll(partialTicks);
|
float anglePitch = entity.getPitch(partialTicks);
|
||||||
|
float angleRoll = entity.getRoll(partialTicks);
|
||||||
float angleYaw = (float) (degYaw / 180 * Math.PI);
|
|
||||||
float anglePitch = (float) (degPitch / 180 * Math.PI);
|
|
||||||
float angleRoll = (float) (degRoll / 180 * Math.PI);
|
|
||||||
|
|
||||||
ms.push();
|
ms.push();
|
||||||
Entity ridingEntity = entity.getRidingEntity();
|
Entity ridingEntity = entity.getRidingEntity();
|
||||||
|
@ -80,7 +77,10 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
|
||||||
MatrixStacker.of(stack)
|
MatrixStacker.of(stack)
|
||||||
.nudge(entity.getEntityId())
|
.nudge(entity.getEntityId())
|
||||||
.centre()
|
.centre()
|
||||||
.rotateRadians(angleRoll, angleYaw, anglePitch)
|
.rotateY(angleYaw)
|
||||||
|
.rotateZ(anglePitch)
|
||||||
|
.rotateY(angleInitialYaw)
|
||||||
|
.rotateX(angleRoll)
|
||||||
.unCentre();
|
.unCentre();
|
||||||
ContraptionRenderer.render(entity.world, entity.getContraption(), ms, msLocal, buffers);
|
ContraptionRenderer.render(entity.world, entity.getContraption(), ms, msLocal, buffers);
|
||||||
ms.pop();
|
ms.pop();
|
||||||
|
|
|
@ -78,8 +78,8 @@ public class ContraptionHandlerClient {
|
||||||
for (ContraptionEntity contraptionEntity : mc.world.getEntitiesWithinAABB(ContraptionEntity.class,
|
for (ContraptionEntity contraptionEntity : mc.world.getEntitiesWithinAABB(ContraptionEntity.class,
|
||||||
new AxisAlignedBB(origin, target))) {
|
new AxisAlignedBB(origin, target))) {
|
||||||
|
|
||||||
Vec3d localOrigin = contraptionEntity.toLocalVector(origin);
|
Vec3d localOrigin = contraptionEntity.toLocalVector(origin, 1);
|
||||||
Vec3d localTarget = contraptionEntity.toLocalVector(target);
|
Vec3d localTarget = contraptionEntity.toLocalVector(target, 1);
|
||||||
Contraption contraption = contraptionEntity.getContraption();
|
Contraption contraption = contraptionEntity.getContraption();
|
||||||
|
|
||||||
MutableObject<BlockRayTraceResult> mutableResult = new MutableObject<>();
|
MutableObject<BlockRayTraceResult> mutableResult = new MutableObject<>();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement;
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -15,7 +17,7 @@ public class MovementContext {
|
||||||
public Vec3d position;
|
public Vec3d position;
|
||||||
public Vec3d motion;
|
public Vec3d motion;
|
||||||
public Vec3d relativeMotion;
|
public Vec3d relativeMotion;
|
||||||
public Vec3d rotation;
|
public UnaryOperator<Vec3d> rotation;
|
||||||
public World world;
|
public World world;
|
||||||
public BlockState state;
|
public BlockState state;
|
||||||
public BlockPos localPos;
|
public BlockPos localPos;
|
||||||
|
@ -36,7 +38,7 @@ public class MovementContext {
|
||||||
firstMovement = true;
|
firstMovement = true;
|
||||||
motion = Vec3d.ZERO;
|
motion = Vec3d.ZERO;
|
||||||
relativeMotion = Vec3d.ZERO;
|
relativeMotion = Vec3d.ZERO;
|
||||||
rotation = Vec3d.ZERO;
|
rotation = v -> v;
|
||||||
position = null;
|
position = null;
|
||||||
data = new CompoundNBT();
|
data = new CompoundNBT();
|
||||||
stall = false;
|
stall = false;
|
||||||
|
@ -56,7 +58,6 @@ public class MovementContext {
|
||||||
MovementContext context = new MovementContext(world, info);
|
MovementContext context = new MovementContext(world, info);
|
||||||
context.motion = VecHelper.readNBT(nbt.getList("Motion", NBT.TAG_DOUBLE));
|
context.motion = VecHelper.readNBT(nbt.getList("Motion", NBT.TAG_DOUBLE));
|
||||||
context.relativeMotion = VecHelper.readNBT(nbt.getList("RelativeMotion", NBT.TAG_DOUBLE));
|
context.relativeMotion = VecHelper.readNBT(nbt.getList("RelativeMotion", NBT.TAG_DOUBLE));
|
||||||
context.rotation = VecHelper.readNBT(nbt.getList("Rotation", NBT.TAG_DOUBLE));
|
|
||||||
if (nbt.contains("Position"))
|
if (nbt.contains("Position"))
|
||||||
context.position = VecHelper.readNBT(nbt.getList("Position", NBT.TAG_DOUBLE));
|
context.position = VecHelper.readNBT(nbt.getList("Position", NBT.TAG_DOUBLE));
|
||||||
context.stall = nbt.getBoolean("Stall");
|
context.stall = nbt.getBoolean("Stall");
|
||||||
|
@ -68,7 +69,6 @@ public class MovementContext {
|
||||||
public CompoundNBT writeToNBT(CompoundNBT nbt) {
|
public CompoundNBT writeToNBT(CompoundNBT nbt) {
|
||||||
nbt.put("Motion", VecHelper.writeNBT(motion));
|
nbt.put("Motion", VecHelper.writeNBT(motion));
|
||||||
nbt.put("RelativeMotion", VecHelper.writeNBT(relativeMotion));
|
nbt.put("RelativeMotion", VecHelper.writeNBT(relativeMotion));
|
||||||
nbt.put("Rotation", VecHelper.writeNBT(rotation));
|
|
||||||
if (position != null)
|
if (position != null)
|
||||||
nbt.put("Position", VecHelper.writeNBT(position));
|
nbt.put("Position", VecHelper.writeNBT(position));
|
||||||
nbt.putBoolean("Stall", stall);
|
nbt.putBoolean("Stall", stall);
|
||||||
|
|
|
@ -2,6 +2,8 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mo
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -12,11 +14,15 @@ import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode;
|
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController;
|
||||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||||
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
|
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
|
||||||
import com.simibubi.create.content.schematics.ItemRequirement;
|
import com.simibubi.create.content.schematics.ItemRequirement;
|
||||||
import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
|
import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
|
||||||
import com.simibubi.create.foundation.block.ITE;
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.block.AbstractRailBlock;
|
import net.minecraft.block.AbstractRailBlock;
|
||||||
|
@ -58,6 +64,7 @@ import net.minecraft.world.World;
|
||||||
import net.minecraft.world.server.ServerWorld;
|
import net.minecraft.world.server.ServerWorld;
|
||||||
import net.minecraft.world.storage.loot.LootContext;
|
import net.minecraft.world.storage.loot.LootContext;
|
||||||
import net.minecraft.world.storage.loot.LootParameters;
|
import net.minecraft.world.storage.loot.LootParameters;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
public class CartAssemblerBlock extends AbstractRailBlock
|
public class CartAssemblerBlock extends AbstractRailBlock
|
||||||
implements ITE<CartAssemblerTileEntity>, IWrenchable, ISpecialBlockItemRequirement {
|
implements ITE<CartAssemblerTileEntity>, IWrenchable, ISpecialBlockItemRequirement {
|
||||||
|
@ -116,56 +123,64 @@ public class CartAssemblerBlock extends AbstractRailBlock
|
||||||
AbstractMinecartEntity cart) {
|
AbstractMinecartEntity cart) {
|
||||||
if (!canAssembleTo(cart))
|
if (!canAssembleTo(cart))
|
||||||
return;
|
return;
|
||||||
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
withTileEntityDo(world, pos, te -> {
|
withTileEntityDo(world, pos, te -> {
|
||||||
if (te.isMinecartUpdateValid()) {
|
if (!te.isMinecartUpdateValid())
|
||||||
switch (state.get(RAIL_TYPE)) {
|
return;
|
||||||
case POWERED_RAIL:
|
|
||||||
if (state.get(POWERED)) {
|
CartAssemblerAction action = getActionForCart(state, cart);
|
||||||
|
if (action.shouldAssemble())
|
||||||
assemble(world, pos, cart);
|
assemble(world, pos, cart);
|
||||||
|
if (action.shouldDisassemble())
|
||||||
|
disassemble(world, pos, cart);
|
||||||
|
if (action == CartAssemblerAction.ASSEMBLE_ACCELERATE) {
|
||||||
Direction facing = cart.getAdjustedHorizontalFacing();
|
Direction facing = cart.getAdjustedHorizontalFacing();
|
||||||
float speed = getRailMaxSpeed(state, world, pos, cart);
|
float speed = getRailMaxSpeed(state, world, pos, cart);
|
||||||
cart.setMotion(facing.getXOffset() * speed, facing.getYOffset() * speed,
|
cart.setMotion(facing.getXOffset() * speed, facing.getYOffset() * speed, facing.getZOffset() * speed);
|
||||||
facing.getZOffset() * speed);
|
}
|
||||||
} else {
|
if (action == CartAssemblerAction.DISASSEMBLE_BRAKE) {
|
||||||
disassemble(world, pos, cart);
|
|
||||||
Vec3d diff = VecHelper.getCenterOf(pos)
|
Vec3d diff = VecHelper.getCenterOf(pos)
|
||||||
.subtract(cart.getPositionVec());
|
.subtract(cart.getPositionVec());
|
||||||
cart.setMotion(diff.x / 16f, 0, diff.z / 16f);
|
cart.setMotion(diff.x / 16f, 0, diff.z / 16f);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case REGULAR:
|
|
||||||
if (state.get(POWERED)) {
|
|
||||||
assemble(world, pos, cart);
|
|
||||||
} else {
|
|
||||||
disassemble(world, pos, cart);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ACTIVATOR_RAIL:
|
|
||||||
if (state.get(POWERED)) {
|
|
||||||
disassemble(world, pos, cart);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DETECTOR_RAIL:
|
|
||||||
if (cart.getPassengers()
|
|
||||||
.isEmpty()) {
|
|
||||||
assemble(world, pos, cart);
|
|
||||||
Direction facing = cart.getAdjustedHorizontalFacing();
|
|
||||||
float speed = getRailMaxSpeed(state, world, pos, cart);
|
|
||||||
cart.setMotion(facing.getXOffset() * speed, facing.getYOffset() * speed,
|
|
||||||
facing.getZOffset() * speed);
|
|
||||||
} else {
|
|
||||||
disassemble(world, pos, cart);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
te.resetTicksSinceMinecartUpdate();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum CartAssemblerAction {
|
||||||
|
ASSEMBLE, DISASSEMBLE, ASSEMBLE_ACCELERATE, DISASSEMBLE_BRAKE, PASS;
|
||||||
|
|
||||||
|
public boolean shouldAssemble() {
|
||||||
|
return this == ASSEMBLE || this == ASSEMBLE_ACCELERATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldDisassemble() {
|
||||||
|
return this == DISASSEMBLE || this == DISASSEMBLE_BRAKE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CartAssemblerAction getActionForCart(BlockState state, AbstractMinecartEntity cart) {
|
||||||
|
CartAssembleRailType type = state.get(RAIL_TYPE);
|
||||||
|
boolean powered = state.get(POWERED);
|
||||||
|
|
||||||
|
if (type == CartAssembleRailType.REGULAR)
|
||||||
|
return powered ? CartAssemblerAction.ASSEMBLE : CartAssemblerAction.DISASSEMBLE;
|
||||||
|
|
||||||
|
if (type == CartAssembleRailType.ACTIVATOR_RAIL)
|
||||||
|
return powered ? CartAssemblerAction.DISASSEMBLE : CartAssemblerAction.PASS;
|
||||||
|
|
||||||
|
if (type == CartAssembleRailType.POWERED_RAIL)
|
||||||
|
return powered ? CartAssemblerAction.ASSEMBLE_ACCELERATE : CartAssemblerAction.DISASSEMBLE_BRAKE;
|
||||||
|
|
||||||
|
if (type == CartAssembleRailType.DETECTOR_RAIL)
|
||||||
|
return cart.getPassengers()
|
||||||
|
.isEmpty() ? CartAssemblerAction.ASSEMBLE_ACCELERATE : CartAssemblerAction.DISASSEMBLE;
|
||||||
|
|
||||||
|
return CartAssemblerAction.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canAssembleTo(AbstractMinecartEntity cart) {
|
public static boolean canAssembleTo(AbstractMinecartEntity cart) {
|
||||||
return cart.canBeRidden() || cart instanceof FurnaceMinecartEntity || cart instanceof ChestMinecartEntity;
|
return cart.canBeRidden() || cart instanceof FurnaceMinecartEntity || cart instanceof ChestMinecartEntity;
|
||||||
}
|
}
|
||||||
|
@ -204,34 +219,44 @@ public class CartAssemblerBlock extends AbstractRailBlock
|
||||||
.isEmpty())
|
.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
LazyOptional<MinecartController> optional =
|
||||||
|
cart.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY);
|
||||||
|
if (optional.isPresent() && optional.orElse(null)
|
||||||
|
.isCoupledThroughContraption())
|
||||||
|
return;
|
||||||
|
|
||||||
MountedContraption contraption = MountedContraption.assembleMinecart(world, pos);
|
MountedContraption contraption = MountedContraption.assembleMinecart(world, pos);
|
||||||
if (contraption == null)
|
if (contraption == null)
|
||||||
return;
|
return;
|
||||||
if (contraption.blocks.size() == 1)
|
if (contraption.blocks.size() == 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Direction facing = cart.getAdjustedHorizontalFacing();
|
|
||||||
float initialAngle = facing.getHorizontalAngle();
|
|
||||||
|
|
||||||
withTileEntityDo(world, pos, te -> contraption.rotationMode = CartMovementMode.values()[te.movementMode.value]);
|
withTileEntityDo(world, pos, te -> contraption.rotationMode = CartMovementMode.values()[te.movementMode.value]);
|
||||||
|
|
||||||
boolean couplingFound = contraption.connectedCart != null;
|
boolean couplingFound = contraption.connectedCart != null;
|
||||||
|
Optional<Direction> initialOrientation = cart.getMotion()
|
||||||
|
.length() < 1 / 512f ? Optional.empty() : Optional.of(cart.getAdjustedHorizontalFacing());
|
||||||
|
|
||||||
|
if (couplingFound) {
|
||||||
|
cart.setPosition(pos.getX() + .5f, pos.getY(), pos.getZ() + .5f);
|
||||||
|
if (!CouplingHandler.tryToCoupleCarts(null, world, cart.getEntityId(),
|
||||||
|
contraption.connectedCart.getEntityId()))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
|
||||||
|
contraption.initActors(world);
|
||||||
|
contraption.expandBoundsAroundAxis(Axis.Y);
|
||||||
|
|
||||||
if (couplingFound) {
|
if (couplingFound) {
|
||||||
CouplingHandler.tryToCoupleCarts(null, world, cart.getEntityId(),
|
|
||||||
contraption.connectedCart.getEntityId());
|
|
||||||
Vec3d diff = contraption.connectedCart.getPositionVec()
|
Vec3d diff = contraption.connectedCart.getPositionVec()
|
||||||
.subtract(cart.getPositionVec());
|
.subtract(cart.getPositionVec());
|
||||||
initialAngle = Direction.fromAngle(MathHelper.atan2(diff.z, diff.x) * 180 / Math.PI)
|
initialOrientation = Optional.of(Direction.fromAngle(MathHelper.atan2(diff.z, diff.x) * 180 / Math.PI));
|
||||||
.getHorizontalAngle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ContraptionEntity entity = ContraptionEntity.createMounted(world, contraption, initialAngle, facing);
|
ContraptionEntity entity = ContraptionEntity.createMounted(world, contraption, initialOrientation);
|
||||||
|
if (couplingFound)
|
||||||
if (couplingFound) {
|
|
||||||
entity.setCouplingId(cart.getUniqueID());
|
entity.setCouplingId(cart.getUniqueID());
|
||||||
entity.setCoupledCart(contraption.connectedCart.getUniqueID());
|
|
||||||
}
|
|
||||||
|
|
||||||
entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
|
entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
|
||||||
world.addEntity(entity);
|
world.addEntity(entity);
|
||||||
entity.startRiding(cart);
|
entity.startRiding(cart);
|
||||||
|
@ -248,11 +273,44 @@ public class CartAssemblerBlock extends AbstractRailBlock
|
||||||
if (cart.getPassengers()
|
if (cart.getPassengers()
|
||||||
.isEmpty())
|
.isEmpty())
|
||||||
return;
|
return;
|
||||||
if (!(cart.getPassengers()
|
Entity entity = cart.getPassengers()
|
||||||
.get(0) instanceof ContraptionEntity))
|
.get(0);
|
||||||
|
if (!(entity instanceof ContraptionEntity))
|
||||||
return;
|
return;
|
||||||
cart.removePassengers();
|
ContraptionEntity contraption = (ContraptionEntity) entity;
|
||||||
|
UUID couplingId = contraption.getCouplingId();
|
||||||
|
|
||||||
|
if (couplingId == null) {
|
||||||
|
disassembleCart(cart);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Couple<MinecartController> coupledCarts = contraption.getCoupledCartsIfPresent();
|
||||||
|
if (coupledCarts == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Make sure connected cart is present and being disassembled
|
||||||
|
for (boolean current : Iterate.trueAndFalse) {
|
||||||
|
MinecartController minecartController = coupledCarts.get(current);
|
||||||
|
if (minecartController.cart() == cart)
|
||||||
|
continue;
|
||||||
|
BlockPos otherPos = minecartController.cart()
|
||||||
|
.getPosition();
|
||||||
|
BlockState blockState = world.getBlockState(otherPos);
|
||||||
|
if (!AllBlocks.CART_ASSEMBLER.has(blockState))
|
||||||
|
return;
|
||||||
|
if (!getActionForCart(blockState, minecartController.cart()).shouldDisassemble())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (boolean current : Iterate.trueAndFalse)
|
||||||
|
coupledCarts.get(current)
|
||||||
|
.removeConnection(current);
|
||||||
|
disassembleCart(cart);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void disassembleCart(AbstractMinecartEntity cart) {
|
||||||
|
cart.removePassengers();
|
||||||
if (cart instanceof FurnaceMinecartEntity) {
|
if (cart instanceof FurnaceMinecartEntity) {
|
||||||
CompoundNBT nbt = cart.serializeNBT();
|
CompoundNBT nbt = cart.serializeNBT();
|
||||||
nbt.putDouble("PushZ", cart.getMotion().x);
|
nbt.putDouble("PushZ", cart.getMotion().x);
|
||||||
|
|
|
@ -1,140 +0,0 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement.mounted;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
||||||
|
|
||||||
import mcp.MethodsReturnNonnullByDefault;
|
|
||||||
import net.minecraft.inventory.IInventory;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
|
||||||
import net.minecraftforge.items.ItemHandlerHelper;
|
|
||||||
|
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
|
||||||
@ParametersAreNonnullByDefault
|
|
||||||
public class ItemHandlerModifiableFromIInventory implements IItemHandlerModifiable {
|
|
||||||
private final IInventory inventory;
|
|
||||||
|
|
||||||
public ItemHandlerModifiableFromIInventory(IInventory inventory) {
|
|
||||||
this.inventory = inventory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setStackInSlot(int slot, ItemStack stack) {
|
|
||||||
inventory.setInventorySlotContents(slot, stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSlots() {
|
|
||||||
return inventory.getSizeInventory();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack getStackInSlot(int slot) {
|
|
||||||
return inventory.getStackInSlot(slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nonnull
|
|
||||||
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate)
|
|
||||||
{
|
|
||||||
if (stack.isEmpty())
|
|
||||||
return ItemStack.EMPTY;
|
|
||||||
|
|
||||||
if (!isItemValid(slot, stack))
|
|
||||||
return stack;
|
|
||||||
|
|
||||||
validateSlotIndex(slot);
|
|
||||||
|
|
||||||
ItemStack existing = getStackInSlot(slot);
|
|
||||||
|
|
||||||
int limit = getStackLimit(slot, stack);
|
|
||||||
|
|
||||||
if (!existing.isEmpty())
|
|
||||||
{
|
|
||||||
if (!ItemHandlerHelper.canItemStacksStack(stack, existing))
|
|
||||||
return stack;
|
|
||||||
|
|
||||||
limit -= existing.getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (limit <= 0)
|
|
||||||
return stack;
|
|
||||||
|
|
||||||
boolean reachedLimit = stack.getCount() > limit;
|
|
||||||
|
|
||||||
if (!simulate)
|
|
||||||
{
|
|
||||||
if (existing.isEmpty())
|
|
||||||
{
|
|
||||||
setStackInSlot(slot, reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, limit) : stack);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
existing.grow(reachedLimit ? limit : stack.getCount());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, stack.getCount()- limit) : ItemStack.EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nonnull
|
|
||||||
public ItemStack extractItem(int slot, int amount, boolean simulate)
|
|
||||||
{
|
|
||||||
if (amount == 0)
|
|
||||||
return ItemStack.EMPTY;
|
|
||||||
|
|
||||||
validateSlotIndex(slot);
|
|
||||||
|
|
||||||
ItemStack existing = getStackInSlot(slot);
|
|
||||||
|
|
||||||
if (existing.isEmpty())
|
|
||||||
return ItemStack.EMPTY;
|
|
||||||
|
|
||||||
int toExtract = Math.min(amount, existing.getMaxStackSize());
|
|
||||||
|
|
||||||
if (existing.getCount() <= toExtract)
|
|
||||||
{
|
|
||||||
if (!simulate)
|
|
||||||
{
|
|
||||||
setStackInSlot(slot, ItemStack.EMPTY);
|
|
||||||
return existing;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return existing.copy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!simulate)
|
|
||||||
{
|
|
||||||
setStackInSlot(slot, ItemHandlerHelper.copyStackWithSize(existing, existing.getCount() - toExtract));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ItemHandlerHelper.copyStackWithSize(existing, toExtract);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSlotLimit(int slot) {
|
|
||||||
return inventory.getInventoryStackLimit();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isItemValid(int slot, ItemStack stack) {
|
|
||||||
return inventory.isItemValidForSlot(slot, stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateSlotIndex(int slot)
|
|
||||||
{
|
|
||||||
if (slot < 0 || slot >= getSlots())
|
|
||||||
throw new RuntimeException("Slot " + slot + " not in valid range - [0," + getSlots() + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getStackLimit(int slot, ItemStack stack)
|
|
||||||
{
|
|
||||||
return Math.min(getSlotLimit(slot), stack.getMaxStackSize());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,14 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement.mounted;
|
package com.simibubi.create.content.contraptions.components.structureMovement.mounted;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
import net.minecraft.block.AbstractRailBlock;
|
import net.minecraft.block.AbstractRailBlock;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -27,6 +29,7 @@ import net.minecraft.state.properties.RailShape;
|
||||||
import net.minecraft.tags.BlockTags;
|
import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.util.ActionResultType;
|
import net.minecraft.util.ActionResultType;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.NonNullList;
|
import net.minecraft.util.NonNullList;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
@ -154,18 +157,21 @@ public class MinecartContraptionItem extends Item {
|
||||||
CompoundNBT tag = itemstack.getOrCreateTag();
|
CompoundNBT tag = itemstack.getOrCreateTag();
|
||||||
if (tag.contains("Contraption")) {
|
if (tag.contains("Contraption")) {
|
||||||
CompoundNBT contraptionTag = tag.getCompound("Contraption");
|
CompoundNBT contraptionTag = tag.getCompound("Contraption");
|
||||||
float initialAngle = contraptionTag.getFloat("InitialAngle");
|
|
||||||
|
Direction initialOrientation = Direction.SOUTH;
|
||||||
|
if (contraptionTag.contains("InitialOrientation"))
|
||||||
|
initialOrientation = NBTHelper.readEnum(contraptionTag, "InitialOrientation", Direction.class);
|
||||||
|
|
||||||
Contraption mountedContraption = Contraption.fromNBT(world, contraptionTag);
|
Contraption mountedContraption = Contraption.fromNBT(world, contraptionTag);
|
||||||
ContraptionEntity contraption;
|
ContraptionEntity contraptionEntity =
|
||||||
|
ContraptionEntity.createMounted(world, mountedContraption, Optional.of(initialOrientation));
|
||||||
|
|
||||||
if (newFacing != null)
|
if (newFacing != null)
|
||||||
contraption = ContraptionEntity.createMounted(world, mountedContraption, initialAngle, newFacing);
|
contraptionEntity.reOrientate(newFacing.getAxis() == Axis.X ? newFacing : newFacing.getOpposite());
|
||||||
else
|
|
||||||
contraption = ContraptionEntity.createMounted(world, mountedContraption, initialAngle);
|
|
||||||
|
|
||||||
contraption.startRiding(cart);
|
contraptionEntity.startRiding(cart);
|
||||||
contraption.setPosition(cart.getX(), cart.getY(), cart.getZ());
|
contraptionEntity.setPosition(cart.getX(), cart.getY(), cart.getZ());
|
||||||
world.addEntity(contraption);
|
world.addEntity(contraptionEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +224,11 @@ public class MinecartContraptionItem extends Item {
|
||||||
tag.remove("UUID");
|
tag.remove("UUID");
|
||||||
tag.remove("Pos");
|
tag.remove("Pos");
|
||||||
tag.remove("Motion");
|
tag.remove("Motion");
|
||||||
tag.putFloat("InitialAngle", entity.getInitialAngle());
|
|
||||||
|
Optional<Direction> initialOrientation = entity.getInitialOrientation();
|
||||||
|
if (initialOrientation.isPresent())
|
||||||
|
NBTHelper.writeEnum(tag, "InitialOrientation", initialOrientation.orElse(null));
|
||||||
|
|
||||||
stack.getOrCreateTag()
|
stack.getOrCreateTag()
|
||||||
.put("Contraption", tag);
|
.put("Contraption", tag);
|
||||||
return stack;
|
return stack;
|
||||||
|
|
|
@ -29,7 +29,9 @@ import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.IWorld;
|
import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
|
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||||
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||||
|
import net.minecraftforge.items.wrapper.InvWrapper;
|
||||||
|
|
||||||
public class MountedContraption extends Contraption {
|
public class MountedContraption extends Contraption {
|
||||||
|
|
||||||
|
@ -57,10 +59,6 @@ public class MountedContraption extends Contraption {
|
||||||
Axis axis = state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z;
|
Axis axis = state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z;
|
||||||
contraption.add(pos, Pair.of(new BlockInfo(pos, AllBlocks.MINECART_ANCHOR.getDefaultState()
|
contraption.add(pos, Pair.of(new BlockInfo(pos, AllBlocks.MINECART_ANCHOR.getDefaultState()
|
||||||
.with(BlockStateProperties.HORIZONTAL_AXIS, axis), null), null));
|
.with(BlockStateProperties.HORIZONTAL_AXIS, axis), null), null));
|
||||||
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
|
|
||||||
contraption.initActors(world);
|
|
||||||
contraption.expandBoundsAroundAxis(Axis.Y);
|
|
||||||
|
|
||||||
return contraption;
|
return contraption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,35 +73,51 @@ public class MountedContraption extends Contraption {
|
||||||
protected Pair<BlockInfo, TileEntity> capture(World world, BlockPos pos) {
|
protected Pair<BlockInfo, TileEntity> capture(World world, BlockPos pos) {
|
||||||
Pair<BlockInfo, TileEntity> pair = super.capture(world, pos);
|
Pair<BlockInfo, TileEntity> pair = super.capture(world, pos);
|
||||||
BlockInfo capture = pair.getKey();
|
BlockInfo capture = pair.getKey();
|
||||||
if (AllBlocks.CART_ASSEMBLER.has(capture.state)) {
|
if (!AllBlocks.CART_ASSEMBLER.has(capture.state))
|
||||||
if (!pos.equals(anchor)) {
|
return pair;
|
||||||
|
|
||||||
|
Pair<BlockInfo, TileEntity> anchorSwap =
|
||||||
|
Pair.of(new BlockInfo(pos, CartAssemblerBlock.createAnchor(capture.state), null), pair.getValue());
|
||||||
|
if (pos.equals(anchor) || connectedCart != null)
|
||||||
|
return anchorSwap;
|
||||||
|
|
||||||
for (Axis axis : Iterate.axes) {
|
for (Axis axis : Iterate.axes) {
|
||||||
if (axis.isVertical())
|
if (axis.isVertical() || !VecHelper.onSameAxis(anchor, pos, axis))
|
||||||
continue;
|
continue;
|
||||||
if (VecHelper.onSameAxis(anchor, pos, axis) && connectedCart == null) {
|
|
||||||
for (AbstractMinecartEntity abstractMinecartEntity : world
|
for (AbstractMinecartEntity abstractMinecartEntity : world
|
||||||
.getEntitiesWithinAABB(AbstractMinecartEntity.class, new AxisAlignedBB(pos))) {
|
.getEntitiesWithinAABB(AbstractMinecartEntity.class, new AxisAlignedBB(pos))) {
|
||||||
if (!CartAssemblerBlock.canAssembleTo(abstractMinecartEntity))
|
if (!CartAssemblerBlock.canAssembleTo(abstractMinecartEntity))
|
||||||
break;
|
break;
|
||||||
connectedCart = abstractMinecartEntity;
|
connectedCart = abstractMinecartEntity;
|
||||||
addExtraInventories(abstractMinecartEntity);
|
connectedCart.setPosition(pos.getX() + .5, pos.getY(), pos.getZ() + .5f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
return anchorSwap;
|
||||||
return Pair.of(new BlockInfo(pos, CartAssemblerBlock.createAnchor(capture.state), null), pair.getValue());
|
|
||||||
}
|
|
||||||
return pair;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean movementAllowed(World world, BlockPos pos) {
|
protected boolean movementAllowed(World world, BlockPos pos) {
|
||||||
BlockState blockState = world.getBlockState(pos);
|
BlockState blockState = world.getBlockState(pos);
|
||||||
if (!pos.equals(anchor) && AllBlocks.CART_ASSEMBLER.has(blockState))
|
if (!pos.equals(anchor) && AllBlocks.CART_ASSEMBLER.has(blockState))
|
||||||
return true;
|
return testSecondaryCartAssembler(world, blockState, pos);
|
||||||
return super.movementAllowed(world, pos);
|
return super.movementAllowed(world, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean testSecondaryCartAssembler(World world, BlockState state, BlockPos pos) {
|
||||||
|
for (Axis axis : Iterate.axes) {
|
||||||
|
if (axis.isVertical() || !VecHelper.onSameAxis(anchor, pos, axis))
|
||||||
|
continue;
|
||||||
|
for (AbstractMinecartEntity abstractMinecartEntity : world
|
||||||
|
.getEntitiesWithinAABB(AbstractMinecartEntity.class, new AxisAlignedBB(pos))) {
|
||||||
|
if (!CartAssemblerBlock.canAssembleTo(abstractMinecartEntity))
|
||||||
|
break;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT writeNBT() {
|
public CompoundNBT writeNBT() {
|
||||||
CompoundNBT writeNBT = super.writeNBT();
|
CompoundNBT writeNBT = super.writeNBT();
|
||||||
|
@ -129,7 +143,9 @@ public class MountedContraption extends Contraption {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addExtraInventories(Entity cart) {
|
public void addExtraInventories(Entity cart) {
|
||||||
if (cart instanceof IInventory)
|
if (!(cart instanceof IInventory))
|
||||||
inventory = new CombinedInvWrapper(new ItemHandlerModifiableFromIInventory((IInventory) cart), inventory);
|
return;
|
||||||
|
IItemHandlerModifiable handlerFromInv = new InvWrapper((IInventory) cart);
|
||||||
|
inventory = new CombinedInvWrapper(handlerFromInv, inventory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
@ -22,9 +23,30 @@ import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
import net.minecraftforge.event.entity.EntityMountEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.Event.Result;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
|
|
||||||
|
@EventBusSubscriber
|
||||||
public class CouplingHandler {
|
public class CouplingHandler {
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void preventEntitiesFromMoutingOccupiedCart(EntityMountEvent event) {
|
||||||
|
Entity e = event.getEntityBeingMounted();
|
||||||
|
LazyOptional<MinecartController> optional = e.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY);
|
||||||
|
if (!optional.isPresent())
|
||||||
|
return;
|
||||||
|
if (event.getEntityMounting() instanceof ContraptionEntity)
|
||||||
|
return;
|
||||||
|
MinecartController controller = optional.orElse(null);
|
||||||
|
if (controller.isCoupledThroughContraption()) {
|
||||||
|
event.setCanceled(true);
|
||||||
|
event.setResult(Result.DENY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void forEachLoadedCoupling(World world, Consumer<Couple<MinecartController>> consumer) {
|
public static void forEachLoadedCoupling(World world, Consumer<Couple<MinecartController>> consumer) {
|
||||||
if (world == null)
|
if (world == null)
|
||||||
return;
|
return;
|
||||||
|
@ -45,14 +67,14 @@ public class CouplingHandler {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tryToCoupleCarts(@Nullable PlayerEntity player, World world, int cartId1, int cartId2) {
|
public static boolean tryToCoupleCarts(@Nullable PlayerEntity player, World world, int cartId1, int cartId2) {
|
||||||
Entity entity1 = world.getEntityByID(cartId1);
|
Entity entity1 = world.getEntityByID(cartId1);
|
||||||
Entity entity2 = world.getEntityByID(cartId2);
|
Entity entity2 = world.getEntityByID(cartId2);
|
||||||
|
|
||||||
if (!(entity1 instanceof AbstractMinecartEntity))
|
if (!(entity1 instanceof AbstractMinecartEntity))
|
||||||
return;
|
return false;
|
||||||
if (!(entity2 instanceof AbstractMinecartEntity))
|
if (!(entity2 instanceof AbstractMinecartEntity))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
String tooMany = "two_couplings_max";
|
String tooMany = "two_couplings_max";
|
||||||
String unloaded = "unloaded";
|
String unloaded = "unloaded";
|
||||||
|
@ -61,16 +83,17 @@ public class CouplingHandler {
|
||||||
|
|
||||||
int distanceTo = (int) entity1.getPositionVec()
|
int distanceTo = (int) entity1.getPositionVec()
|
||||||
.distanceTo(entity2.getPositionVec());
|
.distanceTo(entity2.getPositionVec());
|
||||||
|
boolean contraptionCoupling = player == null;
|
||||||
|
|
||||||
if (distanceTo < 2) {
|
if (distanceTo < 2) {
|
||||||
if (player == null)
|
if (contraptionCoupling)
|
||||||
return; // dont allow train contraptions with <2 distance
|
return false; // dont allow train contraptions with <2 distance
|
||||||
distanceTo = 2;
|
distanceTo = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (distanceTo > AllConfigs.SERVER.kinetics.maxCartCouplingLength.get()) {
|
if (distanceTo > AllConfigs.SERVER.kinetics.maxCartCouplingLength.get()) {
|
||||||
status(player, tooFar);
|
status(player, tooFar);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractMinecartEntity cart1 = (AbstractMinecartEntity) entity1;
|
AbstractMinecartEntity cart1 = (AbstractMinecartEntity) entity1;
|
||||||
|
@ -82,18 +105,18 @@ public class CouplingHandler {
|
||||||
|
|
||||||
if (mainController == null || connectedController == null) {
|
if (mainController == null || connectedController == null) {
|
||||||
status(player, unloaded);
|
status(player, unloaded);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
if (mainController.isFullyCoupled() || connectedController.isFullyCoupled()) {
|
if (mainController.isFullyCoupled() || connectedController.isFullyCoupled()) {
|
||||||
status(player, tooMany);
|
status(player, tooMany);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mainController.isLeadingCoupling() && mainController.getCoupledCart(true)
|
if (mainController.isLeadingCoupling() && mainController.getCoupledCart(true)
|
||||||
.equals(connectedID) || connectedController.isLeadingCoupling()
|
.equals(connectedID) || connectedController.isLeadingCoupling()
|
||||||
&& connectedController.getCoupledCart(true)
|
&& connectedController.getCoupledCart(true)
|
||||||
.equals(mainID))
|
.equals(mainID))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
for (boolean main : Iterate.trueAndFalse) {
|
for (boolean main : Iterate.trueAndFalse) {
|
||||||
MinecartController current = main ? mainController : connectedController;
|
MinecartController current = main ? mainController : connectedController;
|
||||||
|
@ -103,24 +126,24 @@ public class CouplingHandler {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (safetyCount-- <= 0) {
|
if (safetyCount-- <= 0) {
|
||||||
Create.logger.warn("Infinite loop in coupling iteration");
|
Create.logger.warn("Infinite loop in coupling iteration");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
current = getNextInCouplingChain(world, current, forward);
|
current = getNextInCouplingChain(world, current, forward);
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
status(player, unloaded);
|
status(player, unloaded);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
if (current == connectedController) {
|
if (current == connectedController) {
|
||||||
status(player, noLoops);
|
status(player, noLoops);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
if (current == MinecartController.EMPTY)
|
if (current == MinecartController.EMPTY)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player != null) {
|
if (!contraptionCoupling) {
|
||||||
for (Hand hand : Hand.values()) {
|
for (Hand hand : Hand.values()) {
|
||||||
if (player.isCreative())
|
if (player.isCreative())
|
||||||
break;
|
break;
|
||||||
|
@ -135,8 +158,9 @@ public class CouplingHandler {
|
||||||
mainController.prepareForCoupling(true);
|
mainController.prepareForCoupling(true);
|
||||||
connectedController.prepareForCoupling(false);
|
connectedController.prepareForCoupling(false);
|
||||||
|
|
||||||
mainController.coupleWith(true, connectedID, distanceTo);
|
mainController.coupleWith(true, connectedID, distanceTo, contraptionCoupling);
|
||||||
connectedController.coupleWith(false, mainID, distanceTo);
|
connectedController.coupleWith(false, mainID, distanceTo, contraptionCoupling);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
|
@ -32,7 +32,11 @@ public class CouplingRenderer {
|
||||||
|
|
||||||
public static void renderAll(MatrixStack ms, IRenderTypeBuffer buffer) {
|
public static void renderAll(MatrixStack ms, IRenderTypeBuffer buffer) {
|
||||||
CouplingHandler.forEachLoadedCoupling(Minecraft.getInstance().world,
|
CouplingHandler.forEachLoadedCoupling(Minecraft.getInstance().world,
|
||||||
c -> CouplingRenderer.renderCoupling(ms, buffer, c.map(MinecartController::cart)));
|
c -> {
|
||||||
|
if (c.getFirst().hasContraptionCoupling(true))
|
||||||
|
return;
|
||||||
|
CouplingRenderer.renderCoupling(ms, buffer, c.map(MinecartController::cart));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tickDebugModeRenders() {
|
public static void tickDebugModeRenders() {
|
||||||
|
|
|
@ -2,16 +2,15 @@ package com.simibubi.create.content.contraptions.components.structureMovement.tr
|
||||||
|
|
||||||
import static net.minecraft.entity.Entity.horizontalMag;
|
import static net.minecraft.entity.Entity.horizontalMag;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController;
|
||||||
|
|
||||||
import net.minecraft.block.AbstractRailBlock;
|
import net.minecraft.block.AbstractRailBlock;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
import net.minecraft.entity.item.minecart.FurnaceMinecartEntity;
|
import net.minecraft.entity.item.minecart.FurnaceMinecartEntity;
|
||||||
import net.minecraft.state.properties.RailShape;
|
import net.minecraft.state.properties.RailShape;
|
||||||
|
@ -21,6 +20,7 @@ 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;
|
||||||
import net.minecraft.util.math.Vec3i;
|
import net.minecraft.util.math.Vec3i;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Useful methods for dealing with Minecarts
|
* Useful methods for dealing with Minecarts
|
||||||
|
@ -47,10 +47,10 @@ public class MinecartSim2020 {
|
||||||
});
|
});
|
||||||
|
|
||||||
public static Vec3d predictMotionOf(AbstractMinecartEntity cart) {
|
public static Vec3d predictMotionOf(AbstractMinecartEntity cart) {
|
||||||
if (cart instanceof FurnaceMinecartEntity) {
|
// if (cart instanceof FurnaceMinecartEntity) {
|
||||||
return cart.getPositionVec()
|
// return cart.getPositionVec()
|
||||||
.subtract(cart.lastTickPosX, cart.lastTickPosY, cart.lastTickPosZ);
|
// .subtract(cart.lastTickPosX, cart.lastTickPosY, cart.lastTickPosZ);
|
||||||
}
|
// }
|
||||||
return cart.getMotion().scale(1f);
|
return cart.getMotion().scale(1f);
|
||||||
// if (cart instanceof ContainerMinecartEntity) {
|
// if (cart instanceof ContainerMinecartEntity) {
|
||||||
// ContainerMinecartEntity containerCart = (ContainerMinecartEntity) cart;
|
// ContainerMinecartEntity containerCart = (ContainerMinecartEntity) cart;
|
||||||
|
@ -71,15 +71,9 @@ public class MinecartSim2020 {
|
||||||
if (c instanceof FurnaceMinecartEntity)
|
if (c instanceof FurnaceMinecartEntity)
|
||||||
return MathHelper.epsilonEquals(((FurnaceMinecartEntity) c).pushX, 0)
|
return MathHelper.epsilonEquals(((FurnaceMinecartEntity) c).pushX, 0)
|
||||||
&& MathHelper.epsilonEquals(((FurnaceMinecartEntity) c).pushZ, 0);
|
&& MathHelper.epsilonEquals(((FurnaceMinecartEntity) c).pushZ, 0);
|
||||||
List<Entity> passengers = c.getPassengers();
|
LazyOptional<MinecartController> capability = c.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY);
|
||||||
if (passengers.isEmpty())
|
if (capability.isPresent() && capability.orElse(null).isStalled())
|
||||||
return true;
|
return false;
|
||||||
for (Entity entity : passengers) {
|
|
||||||
if (entity instanceof ContraptionEntity) {
|
|
||||||
ContraptionEntity contraptionEntity = (ContraptionEntity) entity;
|
|
||||||
return !contraptionEntity.isStalled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,8 @@ public class CapabilityMinecartController implements ICapabilitySerializable<Com
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
next.removeConnection(!forward);
|
next.removeConnection(!forward);
|
||||||
|
if (controller.hasContraptionCoupling(forward))
|
||||||
|
continue;
|
||||||
AbstractMinecartEntity cart = next.cart();
|
AbstractMinecartEntity cart = next.cart();
|
||||||
if (cart == null)
|
if (cart == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -11,11 +11,14 @@ import javax.annotation.Nullable;
|
||||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
|
||||||
import com.simibubi.create.foundation.networking.AllPackets;
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.nbt.NBTUtil;
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
@ -72,7 +75,7 @@ public class MinecartController implements INBTSerializable<CompoundNBT> {
|
||||||
UUID idOfOther = cd.idOfCart(!main);
|
UUID idOfOther = cd.idOfCart(!main);
|
||||||
MinecartController otherCart = CapabilityMinecartController.getIfPresent(world, idOfOther);
|
MinecartController otherCart = CapabilityMinecartController.getIfPresent(world, idOfOther);
|
||||||
internalStall.setValue(
|
internalStall.setValue(
|
||||||
internalStall.booleanValue() || otherCart == null || !otherCart.isPresent() || otherCart.isStalled());
|
internalStall.booleanValue() || otherCart == null || !otherCart.isPresent() || otherCart.isStalled(false));
|
||||||
|
|
||||||
}));
|
}));
|
||||||
if (!world.isRemote)
|
if (!world.isRemote)
|
||||||
|
@ -93,6 +96,18 @@ public class MinecartController implements INBTSerializable<CompoundNBT> {
|
||||||
.isPresent();
|
.isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCoupledThroughContraption() {
|
||||||
|
for (boolean current : Iterate.trueAndFalse)
|
||||||
|
if (hasContraptionCoupling(current))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasContraptionCoupling(boolean current) {
|
||||||
|
Optional<CouplingData> optional = couplings.get(current);
|
||||||
|
return optional.isPresent() && optional.get().contraption;
|
||||||
|
}
|
||||||
|
|
||||||
public float getCouplingLength(boolean leading) {
|
public float getCouplingLength(boolean leading) {
|
||||||
Optional<CouplingData> optional = couplings.get(leading);
|
Optional<CouplingData> optional = couplings.get(leading);
|
||||||
if (optional.isPresent())
|
if (optional.isPresent())
|
||||||
|
@ -113,6 +128,15 @@ public class MinecartController implements INBTSerializable<CompoundNBT> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeConnection(boolean main) {
|
public void removeConnection(boolean main) {
|
||||||
|
if (hasContraptionCoupling(main) && !getWorld().isRemote) {
|
||||||
|
List<Entity> passengers = cart().getPassengers();
|
||||||
|
if (!passengers.isEmpty()) {
|
||||||
|
Entity entity = passengers.get(0);
|
||||||
|
if (entity instanceof ContraptionEntity)
|
||||||
|
((ContraptionEntity) entity).disassemble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
couplings.set(main, Optional.empty());
|
couplings.set(main, Optional.empty());
|
||||||
needsEntryRefresh |= main;
|
needsEntryRefresh |= main;
|
||||||
sendData();
|
sendData();
|
||||||
|
@ -140,7 +164,28 @@ public class MinecartController implements INBTSerializable<CompoundNBT> {
|
||||||
|
|
||||||
for (MinecartController minecartController : cartsToFlip) {
|
for (MinecartController minecartController : cartsToFlip) {
|
||||||
MinecartController mc = minecartController;
|
MinecartController mc = minecartController;
|
||||||
mc.couplings.forEach(opt -> opt.ifPresent(CouplingData::flip));
|
mc.couplings.forEachWithContext((opt, leading) -> opt.ifPresent(cd -> {
|
||||||
|
cd.flip();
|
||||||
|
if (!cd.contraption)
|
||||||
|
return;
|
||||||
|
List<Entity> passengers = mc.cart()
|
||||||
|
.getPassengers();
|
||||||
|
if (passengers.isEmpty())
|
||||||
|
return;
|
||||||
|
Entity entity = passengers.get(0);
|
||||||
|
if (!(entity instanceof ContraptionEntity))
|
||||||
|
return;
|
||||||
|
ContraptionEntity contraption = (ContraptionEntity) entity;
|
||||||
|
UUID couplingId = contraption.getCouplingId();
|
||||||
|
if (couplingId == cd.mainCartID) {
|
||||||
|
contraption.setCouplingId(cd.connectedCartID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (couplingId == cd.connectedCartID) {
|
||||||
|
contraption.setCouplingId(cd.mainCartID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}));
|
||||||
mc.couplings = mc.couplings.swap();
|
mc.couplings = mc.couplings.swap();
|
||||||
if (mc == this)
|
if (mc == this)
|
||||||
continue;
|
continue;
|
||||||
|
@ -150,10 +195,10 @@ public class MinecartController implements INBTSerializable<CompoundNBT> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void coupleWith(boolean isLeading, UUID coupled, float length) {
|
public void coupleWith(boolean isLeading, UUID coupled, float length, boolean contraption) {
|
||||||
UUID mainID = isLeading ? cart().getUniqueID() : coupled;
|
UUID mainID = isLeading ? cart().getUniqueID() : coupled;
|
||||||
UUID connectedID = isLeading ? coupled : cart().getUniqueID();
|
UUID connectedID = isLeading ? coupled : cart().getUniqueID();
|
||||||
couplings.set(isLeading, Optional.of(new CouplingData(mainID, connectedID, length)));
|
couplings.set(isLeading, Optional.of(new CouplingData(mainID, connectedID, length, contraption)));
|
||||||
needsEntryRefresh |= isLeading;
|
needsEntryRefresh |= isLeading;
|
||||||
sendData();
|
sendData();
|
||||||
}
|
}
|
||||||
|
@ -261,11 +306,13 @@ public class MinecartController implements INBTSerializable<CompoundNBT> {
|
||||||
private UUID mainCartID;
|
private UUID mainCartID;
|
||||||
private UUID connectedCartID;
|
private UUID connectedCartID;
|
||||||
private float length;
|
private float length;
|
||||||
|
private boolean contraption;
|
||||||
|
|
||||||
public CouplingData(UUID mainCartID, UUID connectedCartID, float length) {
|
public CouplingData(UUID mainCartID, UUID connectedCartID, float length, boolean contraption) {
|
||||||
this.mainCartID = mainCartID;
|
this.mainCartID = mainCartID;
|
||||||
this.connectedCartID = connectedCartID;
|
this.connectedCartID = connectedCartID;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
|
this.contraption = contraption;
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip() {
|
void flip() {
|
||||||
|
@ -279,13 +326,16 @@ public class MinecartController implements INBTSerializable<CompoundNBT> {
|
||||||
nbt.put("Main", NBTUtil.writeUniqueId(mainCartID));
|
nbt.put("Main", NBTUtil.writeUniqueId(mainCartID));
|
||||||
nbt.put("Connected", NBTUtil.writeUniqueId(connectedCartID));
|
nbt.put("Connected", NBTUtil.writeUniqueId(connectedCartID));
|
||||||
nbt.putFloat("Length", length);
|
nbt.putFloat("Length", length);
|
||||||
|
nbt.putBoolean("Contraption", contraption);
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CouplingData read(CompoundNBT nbt) {
|
static CouplingData read(CompoundNBT nbt) {
|
||||||
UUID mainCartID = NBTUtil.readUniqueId(nbt.getCompound("Main"));
|
UUID mainCartID = NBTUtil.readUniqueId(nbt.getCompound("Main"));
|
||||||
UUID connectedCartID = NBTUtil.readUniqueId(nbt.getCompound("Connected"));
|
UUID connectedCartID = NBTUtil.readUniqueId(nbt.getCompound("Connected"));
|
||||||
return new CouplingData(mainCartID, connectedCartID, nbt.getFloat("Length"));
|
float length = nbt.getFloat("Length");
|
||||||
|
boolean contraption = nbt.getBoolean("Contraption");
|
||||||
|
return new CouplingData(mainCartID, connectedCartID, length, contraption);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID idOfCart(boolean main) {
|
public UUID idOfCart(boolean main) {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import java.util.Map;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
|
||||||
|
|
||||||
import net.minecraft.entity.item.ItemEntity;
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -31,7 +30,7 @@ public class BasinMovementBehaviour extends MovementBehaviour {
|
||||||
public void tick(MovementContext context) {
|
public void tick(MovementContext context) {
|
||||||
super.tick(context);
|
super.tick(context);
|
||||||
if (context.temporaryData == null || (boolean) context.temporaryData) {
|
if (context.temporaryData == null || (boolean) context.temporaryData) {
|
||||||
Vec3d facingVec = VecHelper.rotate(new Vec3d(Direction.UP.getDirectionVec()), context.rotation.x, context.rotation.y, context.rotation.z);
|
Vec3d facingVec = context.rotation.apply(new Vec3d(Direction.UP.getDirectionVec()));
|
||||||
facingVec.normalize();
|
facingVec.normalize();
|
||||||
if (Direction.getFacingFromVector(facingVec.x, facingVec.y, facingVec.z) == Direction.DOWN)
|
if (Direction.getFacingFromVector(facingVec.x, facingVec.y, facingVec.z) == Direction.DOWN)
|
||||||
dump(context, facingVec);
|
dump(context, facingVec);
|
||||||
|
@ -41,16 +40,21 @@ public class BasinMovementBehaviour extends MovementBehaviour {
|
||||||
private void dump(MovementContext context, Vec3d facingVec) {
|
private void dump(MovementContext context, Vec3d facingVec) {
|
||||||
getOrReadInventory(context).forEach((key, itemStackHandler) -> {
|
getOrReadInventory(context).forEach((key, itemStackHandler) -> {
|
||||||
for (int i = 0; i < itemStackHandler.getSlots(); i++) {
|
for (int i = 0; i < itemStackHandler.getSlots(); i++) {
|
||||||
if (itemStackHandler.getStackInSlot(i).isEmpty())
|
if (itemStackHandler.getStackInSlot(i)
|
||||||
|
.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
ItemEntity itemEntity = new ItemEntity(context.world, context.position.x, context.position.y, context.position.z, itemStackHandler.getStackInSlot(i));
|
ItemEntity itemEntity = new ItemEntity(context.world, context.position.x, context.position.y,
|
||||||
|
context.position.z, itemStackHandler.getStackInSlot(i));
|
||||||
itemEntity.setMotion(facingVec.scale(.05));
|
itemEntity.setMotion(facingVec.scale(.05));
|
||||||
context.world.addEntity(itemEntity);
|
context.world.addEntity(itemEntity);
|
||||||
itemStackHandler.setStackInSlot(i, ItemStack.EMPTY);
|
itemStackHandler.setStackInSlot(i, ItemStack.EMPTY);
|
||||||
}
|
}
|
||||||
context.tileData.put(key, itemStackHandler.serializeNBT());
|
context.tileData.put(key, itemStackHandler.serializeNBT());
|
||||||
});
|
});
|
||||||
context.contraption.customRenderTEs.stream().filter(te -> te.getPos().equals(context.localPos) && te instanceof BasinTileEntity).forEach(te -> ((BasinTileEntity) te).readOnlyItems(context.tileData));
|
context.contraption.customRenderTEs.stream()
|
||||||
|
.filter(te -> te.getPos()
|
||||||
|
.equals(context.localPos) && te instanceof BasinTileEntity)
|
||||||
|
.forEach(te -> ((BasinTileEntity) te).readOnlyItems(context.tileData));
|
||||||
context.temporaryData = false; // did already dump, so can't any more
|
context.temporaryData = false; // did already dump, so can't any more
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.simibubi.create.content.logistics.block.redstone;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.nbt.NBTUtil;
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
@ -36,7 +35,7 @@ public class ContactMovementBehaviour extends MovementBehaviour {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Vec3d contact = new Vec3d(block.get(RedstoneContactBlock.FACING).getDirectionVec());
|
Vec3d contact = new Vec3d(block.get(RedstoneContactBlock.FACING).getDirectionVec());
|
||||||
contact = VecHelper.rotate(contact, context.rotation.x, context.rotation.y, context.rotation.z);
|
contact = context.rotation.apply(contact);
|
||||||
Direction direction = Direction.getFacingFromVector(contact.x, contact.y, contact.z);
|
Direction direction = Direction.getFacingFromVector(contact.x, contact.y, contact.z);
|
||||||
|
|
||||||
if (!RedstoneContactBlock.hasValidContact(world, pos.offset(direction.getOpposite()), direction))
|
if (!RedstoneContactBlock.hasValidContact(world, pos.offset(direction.getOpposite()), direction))
|
||||||
|
|
|
@ -33,13 +33,6 @@ public class MatrixStacker {
|
||||||
return multiply(Vector3f.POSITIVE_Z, angle);
|
return multiply(Vector3f.POSITIVE_Z, angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MatrixStacker rotateRadians(double angleRoll, double angleYaw, double anglePitch) {
|
|
||||||
rotateX(AngleHelper.deg(angleRoll));
|
|
||||||
rotateY(AngleHelper.deg(angleYaw));
|
|
||||||
rotateZ(AngleHelper.deg(anglePitch));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MatrixStacker centre() {
|
public MatrixStacker centre() {
|
||||||
return translate(center);
|
return translate(center);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue