mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-13 14:04:20 +01:00
Minecart Purgatory
- Further attempts at improving the coupling physics - Fixed reversed couplings losing their physics entry point - Fixed "angel block" placement through super glue
This commit is contained in:
parent
1bebaa6faa
commit
bf869010f0
@ -43,6 +43,7 @@ import net.minecraft.util.math.BlockRayTraceResult;
|
|||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.RayTraceResult;
|
import net.minecraft.util.math.RayTraceResult;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.util.math.RayTraceResult.Type;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
@ -256,26 +257,38 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
|
|||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
private void triggerPlaceBlock(PlayerEntity player, Hand hand) {
|
private void triggerPlaceBlock(PlayerEntity player, Hand hand) {
|
||||||
if (player instanceof ClientPlayerEntity && player.world instanceof ClientWorld) {
|
if (!(player instanceof ClientPlayerEntity))
|
||||||
ClientPlayerEntity cPlayer = (ClientPlayerEntity) player;
|
return;
|
||||||
Minecraft mc = Minecraft.getInstance();
|
if (!(player.world instanceof ClientWorld))
|
||||||
RayTraceResult ray =
|
return;
|
||||||
cPlayer.pick(mc.playerController.getBlockReachDistance(), mc.getRenderPartialTicks(), false);
|
|
||||||
if (ray instanceof BlockRayTraceResult) {
|
ClientPlayerEntity cPlayer = (ClientPlayerEntity) player;
|
||||||
for (Hand handIn : Hand.values()) {
|
Minecraft mc = Minecraft.getInstance();
|
||||||
ItemStack itemstack = cPlayer.getHeldItem(handIn);
|
RayTraceResult ray =
|
||||||
int countBefore = itemstack.getCount();
|
cPlayer.pick(mc.playerController.getBlockReachDistance(), mc.getRenderPartialTicks(), false);
|
||||||
ActionResultType actionResultType = mc.playerController.func_217292_a(cPlayer,
|
|
||||||
(ClientWorld) cPlayer.world, handIn, (BlockRayTraceResult) ray);
|
if (!(ray instanceof BlockRayTraceResult))
|
||||||
if (actionResultType == ActionResultType.SUCCESS) {
|
return;
|
||||||
cPlayer.swingArm(handIn);
|
if (ray.getType() == Type.MISS)
|
||||||
if (!itemstack.isEmpty()
|
return;
|
||||||
&& (itemstack.getCount() != countBefore || mc.playerController.isInCreativeMode()))
|
BlockRayTraceResult blockRay = (BlockRayTraceResult) ray;
|
||||||
mc.gameRenderer.itemRenderer.resetEquippedProgress(handIn);
|
if (!blockRay.getPos()
|
||||||
return;
|
.offset(blockRay.getFace())
|
||||||
}
|
.equals(getHangingPosition()))
|
||||||
}
|
return;
|
||||||
}
|
|
||||||
|
for (Hand handIn : Hand.values()) {
|
||||||
|
ItemStack itemstack = cPlayer.getHeldItem(handIn);
|
||||||
|
int countBefore = itemstack.getCount();
|
||||||
|
ActionResultType actionResultType =
|
||||||
|
mc.playerController.func_217292_a(cPlayer, (ClientWorld) cPlayer.world, handIn, blockRay);
|
||||||
|
if (actionResultType != ActionResultType.SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cPlayer.swingArm(handIn);
|
||||||
|
if (!itemstack.isEmpty() && (itemstack.getCount() != countBefore || mc.playerController.isInCreativeMode()))
|
||||||
|
mc.gameRenderer.itemRenderer.resetEquippedProgress(handIn);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,9 @@ import net.minecraft.entity.Entity;
|
|||||||
import net.minecraft.entity.MoverType;
|
import net.minecraft.entity.MoverType;
|
||||||
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
import net.minecraft.state.properties.RailShape;
|
import net.minecraft.state.properties.RailShape;
|
||||||
|
import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
@ -23,12 +25,18 @@ public class CouplingPhysics {
|
|||||||
|
|
||||||
public static void tickCoupling(World world, Couple<MinecartController> c) {
|
public static void tickCoupling(World world, Couple<MinecartController> c) {
|
||||||
Couple<AbstractMinecartEntity> carts = c.map(MinecartController::cart);
|
Couple<AbstractMinecartEntity> carts = c.map(MinecartController::cart);
|
||||||
float couplingLength = c.getFirst().getCouplingLength(true);
|
float couplingLength = c.getFirst()
|
||||||
|
.getCouplingLength(true);
|
||||||
softCollisionStep(world, carts, couplingLength);
|
softCollisionStep(world, carts, couplingLength);
|
||||||
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
hardCollisionStep(world, carts, couplingLength);
|
hardCollisionStep(world, carts, couplingLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void hardCollisionStep(World world, Couple<AbstractMinecartEntity> carts, double couplingLength) {
|
public static void hardCollisionStep(World world, Couple<AbstractMinecartEntity> carts, double couplingLength) {
|
||||||
|
if (!MinecartSim2020.canAddMotion(carts.get(false)) && MinecartSim2020.canAddMotion(carts.get(true)))
|
||||||
|
carts = carts.swap();
|
||||||
|
|
||||||
Couple<Vec3d> corrections = Couple.create(null, null);
|
Couple<Vec3d> corrections = Couple.create(null, null);
|
||||||
Couple<Float> maxSpeed = carts.map(AbstractMinecartEntity::getMaxCartSpeedOnRail);
|
Couple<Float> maxSpeed = carts.map(AbstractMinecartEntity::getMaxCartSpeedOnRail);
|
||||||
boolean firstLoop = true;
|
boolean firstLoop = true;
|
||||||
@ -39,6 +47,9 @@ public class CouplingPhysics {
|
|||||||
float stress = (float) (couplingLength - cart.getPositionVec()
|
float stress = (float) (couplingLength - cart.getPositionVec()
|
||||||
.distanceTo(otherCart.getPositionVec()));
|
.distanceTo(otherCart.getPositionVec()));
|
||||||
|
|
||||||
|
if (Math.abs(stress) < 1 / 8f)
|
||||||
|
continue;
|
||||||
|
|
||||||
RailShape shape = null;
|
RailShape shape = null;
|
||||||
BlockPos railPosition = cart.getCurrentRailPosition();
|
BlockPos railPosition = cart.getCurrentRailPosition();
|
||||||
BlockState railState = world.getBlockState(railPosition.up());
|
BlockState railState = world.getBlockState(railPosition.up());
|
||||||
@ -53,7 +64,12 @@ public class CouplingPhysics {
|
|||||||
Vec3d link = otherCart.getPositionVec()
|
Vec3d link = otherCart.getPositionVec()
|
||||||
.subtract(pos);
|
.subtract(pos);
|
||||||
float correctionMagnitude = firstLoop ? -stress / 2f : -stress;
|
float correctionMagnitude = firstLoop ? -stress / 2f : -stress;
|
||||||
correction = shape != null ? followLinkOnRail(link, pos, correctionMagnitude, shape).subtract(pos)
|
|
||||||
|
if (!MinecartSim2020.canAddMotion(cart))
|
||||||
|
correctionMagnitude /= 2;
|
||||||
|
|
||||||
|
correction = shape != null
|
||||||
|
? followLinkOnRail(link, pos, correctionMagnitude, MinecartSim2020.getRailVec(shape)).subtract(pos)
|
||||||
: link.normalize()
|
: link.normalize()
|
||||||
.scale(correctionMagnitude);
|
.scale(correctionMagnitude);
|
||||||
|
|
||||||
@ -75,27 +91,30 @@ public class CouplingPhysics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void softCollisionStep(World world, Couple<AbstractMinecartEntity> carts, double couplingLength) {
|
public static void softCollisionStep(World world, Couple<AbstractMinecartEntity> carts, double couplingLength) {
|
||||||
|
|
||||||
Couple<Vec3d> positions = carts.map(Entity::getPositionVector);
|
|
||||||
Couple<Float> maxSpeed = carts.map(AbstractMinecartEntity::getMaxCartSpeedOnRail);
|
Couple<Float> maxSpeed = carts.map(AbstractMinecartEntity::getMaxCartSpeedOnRail);
|
||||||
Couple<Boolean> canAddmotion = carts.map(MinecartSim2020::canAddMotion);
|
Couple<Boolean> canAddmotion = carts.map(MinecartSim2020::canAddMotion);
|
||||||
|
Couple<Vec3d> motions = carts.map(Entity::getMotion);
|
||||||
|
Couple<Vec3d> nextPositions = carts.map(MinecartSim2020::predictNextPositionOf);
|
||||||
|
|
||||||
Couple<RailShape> shapes = carts.map(current -> {
|
Couple<RailShape> shapes = carts.mapWithContext((cart, current) -> {
|
||||||
BlockPos railPosition = current.getCurrentRailPosition();
|
AbstractMinecartEntity minecart = cart.getMinecart();
|
||||||
|
Vec3d vec = nextPositions.get(current);
|
||||||
|
int x = MathHelper.floor(vec.getX());
|
||||||
|
int y = MathHelper.floor(vec.getY());
|
||||||
|
int z = MathHelper.floor(vec.getZ());
|
||||||
|
BlockPos pos = new BlockPos(x, y - 1, z);
|
||||||
|
if (minecart.world.getBlockState(pos).isIn(BlockTags.RAILS)) pos = pos.down();
|
||||||
|
BlockPos railPosition = pos;
|
||||||
BlockState railState = world.getBlockState(railPosition.up());
|
BlockState railState = world.getBlockState(railPosition.up());
|
||||||
if (!(railState.getBlock() instanceof AbstractRailBlock))
|
if (!(railState.getBlock() instanceof AbstractRailBlock))
|
||||||
return null;
|
return null;
|
||||||
AbstractRailBlock block = (AbstractRailBlock) railState.getBlock();
|
AbstractRailBlock block = (AbstractRailBlock) railState.getBlock();
|
||||||
return block.getRailDirection(railState, world, railPosition, current);
|
return block.getRailDirection(railState, world, railPosition, cart);
|
||||||
});
|
});
|
||||||
|
|
||||||
Couple<Vec3d> motions = carts.map(MinecartSim2020::predictMotionOf);
|
|
||||||
Couple<Vec3d> nextPositions = positions.copy();
|
|
||||||
nextPositions.replaceWithParams(Vec3d::add, motions);
|
|
||||||
|
|
||||||
float futureStress = (float) (couplingLength - nextPositions.getFirst()
|
float futureStress = (float) (couplingLength - nextPositions.getFirst()
|
||||||
.distanceTo(nextPositions.getSecond()));
|
.distanceTo(nextPositions.getSecond()));
|
||||||
if (Math.abs(futureStress) < 1 / 128f)
|
if (MathHelper.epsilonEquals(futureStress, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (boolean current : Iterate.trueAndFalse) {
|
for (boolean current : Iterate.trueAndFalse) {
|
||||||
@ -107,12 +126,19 @@ public class CouplingPhysics {
|
|||||||
|
|
||||||
if (canAddmotion.get(current) != canAddmotion.get(!current))
|
if (canAddmotion.get(current) != canAddmotion.get(!current))
|
||||||
correctionMagnitude = !canAddmotion.get(current) ? 0 : correctionMagnitude * 2;
|
correctionMagnitude = !canAddmotion.get(current) ? 0 : correctionMagnitude * 2;
|
||||||
|
if (!canAddmotion.get(current))
|
||||||
|
continue;
|
||||||
|
|
||||||
RailShape shape = shapes.get(current);
|
RailShape shape = shapes.get(current);
|
||||||
correction = shape != null ? followLinkOnRail(link, pos, correctionMagnitude, shape).subtract(pos)
|
if (shape != null) {
|
||||||
: link.normalize()
|
Vec3d railVec = MinecartSim2020.getRailVec(shape);
|
||||||
|
correction = followLinkOnRail(link, pos, correctionMagnitude, railVec).subtract(pos);
|
||||||
|
} else
|
||||||
|
correction = link.normalize()
|
||||||
.scale(correctionMagnitude);
|
.scale(correctionMagnitude);
|
||||||
|
|
||||||
correction = VecHelper.clamp(correction, maxSpeed.get(current));
|
correction = VecHelper.clamp(correction, maxSpeed.get(current));
|
||||||
|
|
||||||
motions.set(current, motions.get(current)
|
motions.set(current, motions.get(current)
|
||||||
.add(correction));
|
.add(correction));
|
||||||
}
|
}
|
||||||
@ -121,8 +147,7 @@ public class CouplingPhysics {
|
|||||||
carts.forEachWithParams(Entity::setMotion, motions);
|
carts.forEachWithParams(Entity::setMotion, motions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vec3d followLinkOnRail(Vec3d link, Vec3d cart, float diffToReduce, RailShape shape) {
|
public static Vec3d followLinkOnRail(Vec3d link, Vec3d cart, float diffToReduce, Vec3d railAxis) {
|
||||||
Vec3d railAxis = MinecartSim2020.getRailVec(shape);
|
|
||||||
double dotProduct = railAxis.dotProduct(link);
|
double dotProduct = railAxis.dotProduct(link);
|
||||||
if (Double.isNaN(dotProduct) || dotProduct == 0 || diffToReduce == 0)
|
if (Double.isNaN(dotProduct) || dotProduct == 0 || diffToReduce == 0)
|
||||||
return cart;
|
return cart;
|
||||||
|
@ -46,33 +46,20 @@ public class MinecartSim2020 {
|
|||||||
map.put(RailShape.NORTH_EAST, Pair.of(north, east));
|
map.put(RailShape.NORTH_EAST, Pair.of(north, east));
|
||||||
});
|
});
|
||||||
|
|
||||||
public static Vec3d predictMotionOf(AbstractMinecartEntity cart) {
|
public static Vec3d predictNextPositionOf(AbstractMinecartEntity cart) {
|
||||||
// if (cart instanceof FurnaceMinecartEntity) {
|
Vec3d position = cart.getPositionVec();
|
||||||
// return cart.getPositionVec()
|
Vec3d motion = cart.getMotion();
|
||||||
// .subtract(cart.lastTickPosX, cart.lastTickPosY, cart.lastTickPosZ);
|
return position.add(motion);
|
||||||
// }
|
|
||||||
return cart.getMotion().scale(1f);
|
|
||||||
// if (cart instanceof ContainerMinecartEntity) {
|
|
||||||
// ContainerMinecartEntity containerCart = (ContainerMinecartEntity) cart;
|
|
||||||
// float f = 0.98F;
|
|
||||||
// if (containerCart.isEmpty())
|
|
||||||
// return cart.getMotion()
|
|
||||||
// .mul(f, 0.0D, f);
|
|
||||||
// int i = 15 - Container.calcRedstoneFromInventory(containerCart);
|
|
||||||
// f += (float) i * 0.001F;
|
|
||||||
// return cart.getMotion()
|
|
||||||
// .mul(f, 0.0D, f);
|
|
||||||
// }
|
|
||||||
// return cart.getMotion()
|
|
||||||
// .scale(cart.isBeingRidden() ? 0.997D : 0.96D);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canAddMotion(AbstractMinecartEntity c) {
|
public static boolean canAddMotion(AbstractMinecartEntity c) {
|
||||||
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);
|
||||||
LazyOptional<MinecartController> capability = c.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY);
|
LazyOptional<MinecartController> capability =
|
||||||
if (capability.isPresent() && capability.orElse(null).isStalled())
|
c.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY);
|
||||||
|
if (capability.isPresent() && capability.orElse(null)
|
||||||
|
.isStalled())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -196,21 +183,6 @@ public class MinecartSim2020 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cart.setMotion(previousMotion);
|
cart.setMotion(previousMotion);
|
||||||
|
|
||||||
if (cart instanceof FurnaceMinecartEntity) {
|
|
||||||
// FurnaceMinecartEntity furnaceCart = (FurnaceMinecartEntity) cart;
|
|
||||||
// Vec3d vec3d = cart.getMotion();
|
|
||||||
// double d2 = horizontalMag(vec3d);
|
|
||||||
// double d3 = furnaceCart.pushX * furnaceCart.pushX + furnaceCart.pushZ * furnaceCart.pushZ;
|
|
||||||
// if (d3 > 1.0E-4D && d2 > 0.001D) {
|
|
||||||
// double d40 = (double) MathHelper.sqrt(d2);
|
|
||||||
// double d50 = (double) MathHelper.sqrt(d3);
|
|
||||||
// furnaceCart.pushX = vec3d.x / d40 * d50;
|
|
||||||
// furnaceCart.pushZ = vec3d.z / d40 * d50;
|
|
||||||
// furnaceCart.setMotion(vec3d.mul(0.8D, 0.0D, 0.8D)
|
|
||||||
// .add(furnaceCart.pushX, 0.0D, furnaceCart.pushZ));
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vec3d getRailVec(RailShape shape) {
|
public static Vec3d getRailVec(RailShape shape) {
|
||||||
|
@ -187,9 +187,9 @@ public class MinecartController implements INBTSerializable<CompoundNBT> {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
mc.couplings = mc.couplings.swap();
|
mc.couplings = mc.couplings.swap();
|
||||||
|
mc.needsEntryRefresh = true;
|
||||||
if (mc == this)
|
if (mc == this)
|
||||||
continue;
|
continue;
|
||||||
mc.needsEntryRefresh = true;
|
|
||||||
mc.sendData();
|
mc.sendData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,8 +114,9 @@ public class ArmInteractionPointHandler {
|
|||||||
else
|
else
|
||||||
inputs++;
|
inputs++;
|
||||||
}
|
}
|
||||||
player.sendStatusMessage(Lang.createTranslationTextComponent("mechanical_arm.summary", inputs, outputs)
|
if (inputs + outputs > 0)
|
||||||
.applyTextStyle(TextFormatting.WHITE), true);
|
player.sendStatusMessage(Lang.createTranslationTextComponent("mechanical_arm.summary", inputs, outputs)
|
||||||
|
.applyTextStyle(TextFormatting.WHITE), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
AllPackets.channel.sendToServer(new ArmPlacementPacket(currentSelection, pos));
|
AllPackets.channel.sendToServer(new ArmPlacementPacket(currentSelection, pos));
|
||||||
|
@ -49,6 +49,14 @@ public class Couple<T> extends Pair<T, T> implements Iterable<T> {
|
|||||||
return Couple.create(function.apply(first), function.apply(second));
|
return Couple.create(function.apply(first), function.apply(second));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <S> Couple<S> mapWithContext(BiFunction<T, Boolean, S> function) {
|
||||||
|
return Couple.create(function.apply(first, true), function.apply(second, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public <S, R> Couple<S> mapWithParams(BiFunction<T, R, S> function, Couple<R> values) {
|
||||||
|
return Couple.create(function.apply(first, values.first), function.apply(second, values.second));
|
||||||
|
}
|
||||||
|
|
||||||
public void replace(Function<T, T> function) {
|
public void replace(Function<T, T> function) {
|
||||||
setFirst(function.apply(getFirst()));
|
setFirst(function.apply(getFirst()));
|
||||||
setSecond(function.apply(getSecond()));
|
setSecond(function.apply(getSecond()));
|
||||||
@ -95,17 +103,17 @@ public class Couple<T> extends Pair<T, T> implements Iterable<T> {
|
|||||||
public Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
return new Couplerator<>(this);
|
return new Couplerator<>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Couplerator<T> implements Iterator<T> {
|
private static class Couplerator<T> implements Iterator<T> {
|
||||||
|
|
||||||
int state;
|
int state;
|
||||||
private Couple<T> couple;
|
private Couple<T> couple;
|
||||||
|
|
||||||
public Couplerator(Couple<T> couple) {
|
public Couplerator(Couple<T> couple) {
|
||||||
this.couple = couple;
|
this.couple = couple;
|
||||||
state = 0;
|
state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return state != 2;
|
return state != 2;
|
||||||
@ -120,7 +128,7 @@ public class Couple<T> extends Pair<T, T> implements Iterable<T> {
|
|||||||
return couple.second;
|
return couple.second;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user