Skip to content

Commit e5df35d

Browse files
committed
Adjustments for the vertical prediction (liquids)
1 parent 5987b4d commit e5df35d

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/player/SurvivalFly.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ public class SurvivalFly extends Check {
8585

8686
private final IGenericInstanceHandle<IAttributeAccess> attributeAccess = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstanceHandle(IAttributeAccess.class);
8787

88+
/**
89+
* The vertical component of liquid push (water/lava).
90+
* This is computed in hdistrel and then used by vidstrel to avoid having to call the getLiquidPush() method twice.
91+
* When computing the horizontal liquid push, the way Mojang coded the function to get the liquid's flowing force
92+
* to calculate horizontal speed with, also affects the vertical speed (See comment in {@link fr.neatmonster.nocheatplus.utilities.location.RichEntityLocation#getFlowForceVector(int, int, int, long)}.
93+
*/
94+
private double verticalLiquidPushComponent = 0.0;
95+
8896

8997
public SurvivalFly() {
9098
super(CheckType.MOVING_SURVIVALFLY);
@@ -1020,6 +1028,7 @@ private boolean estimateNextSpeed(final Player player, float movementSpeed, fina
10201028
if (from.isInLiquid()) {
10211029
Vector liquidFlowVector = from.getLiquidPushingVector(thisMove.xAllowedDistance, thisMove.zAllowedDistance, from.isInWater() ? BlockFlags.F_WATER : BlockFlags.F_LAVA);
10221030
thisMove.xAllowedDistance += liquidFlowVector.getX();
1031+
verticalLiquidPushComponent = liquidFlowVector.getY();
10231032
thisMove.zAllowedDistance += liquidFlowVector.getZ();
10241033
}
10251034
// Before calculating the acceleration, check if momentum is below the negligible speed threshold and cancel it.
@@ -1035,20 +1044,25 @@ private boolean estimateNextSpeed(final Player player, float movementSpeed, fina
10351044
}
10361045
tags.add("bunnyhop");
10371046
}
1038-
1047+
1048+
/*
1049+
* This bit of vertical distance computation is needed for the supporting block mechanism, which needs Minecraft-calculated on-ground status.
1050+
* Normally, these would be computed at the same time, however, since NCP handles horizontal and vertical speed estimation separately, we need to duplicate this bit of code here.
1051+
* TODO: Unify predictions somehow.
1052+
*/
10391053
// Current yDistance before calculation for supporting block ground state. Copy paste from vDistrel
10401054
double yDistanceBeforeCollide = lastMove.toIsValid ? lastMove.yDistance : 0.0;
10411055
if (lastMove.from.inWater) {
10421056
yDistanceBeforeCollide *= data.lastFrictionVertical;
1043-
//TODO: this or last
1044-
Vector fluidFallingAdjustMovement = from.getFluidFallingAdjustedMovement(data.lastGravity, lastMove.yAllowedDistance <= 0.0, new Vector(0.0, lastMove.yAllowedDistance, 0.0), cData.wasSprinting);
1057+
// NOTE: For fluid falling, it should be thisMove not last. the allowed distance is already initialised with lastMove's distance; calling the last ALLOWED distance, would basically mean using the momentum of the second last move, which is incorrect.
1058+
// Here, we use yDistanceBeforeCollide as thisMove.yAllowedDistance has not yet been calculated at this point.
1059+
Vector fluidFallingAdjustMovement = from.getFluidFallingAdjustedMovement(data.lastGravity, yDistanceBeforeCollide <= 0.0, new Vector(0.0, yDistanceBeforeCollide, 0.0), cData.wasSprinting);
10451060
yDistanceBeforeCollide = fluidFallingAdjustMovement.getY();
10461061
}
10471062
else if (lastMove.from.inLava) {
10481063
if (data.lastFrictionVertical != Magic.LAVA_VERTICAL_INERTIA) {
10491064
yDistanceBeforeCollide *= data.lastFrictionVertical;
1050-
//TODO: this or last
1051-
Vector fluidFallingAdjustMovement = from.getFluidFallingAdjustedMovement(data.lastGravity, lastMove.yAllowedDistance <= 0.0, new Vector(0.0, lastMove.yAllowedDistance, 0.0), cData.wasSprinting);
1065+
Vector fluidFallingAdjustMovement = from.getFluidFallingAdjustedMovement(data.lastGravity, yDistanceBeforeCollide <= 0.0, new Vector(0.0, yDistanceBeforeCollide, 0.0), cData.wasSprinting);
10521066
yDistanceBeforeCollide = fluidFallingAdjustMovement.getY();
10531067
}
10541068
else {
@@ -1061,7 +1075,7 @@ else if (lastMove.from.inLava) {
10611075
else {
10621076
// Air motion
10631077
if (cData.wasLevitating) {
1064-
yDistanceBeforeCollide += (0.05 * data.lastLevitationLevel - lastMove.yAllowedDistance) * 0.2;
1078+
yDistanceBeforeCollide += (0.05 * data.lastLevitationLevel - yDistanceBeforeCollide) * 0.2;
10651079
}
10661080
else yDistanceBeforeCollide -= data.lastGravity;
10671081
yDistanceBeforeCollide *= data.lastFrictionVertical;
@@ -1541,7 +1555,7 @@ private double[] vDistRel(final Player player, final PlayerLocation from,
15411555
// Water applies friction before calling the fluidFalling function.
15421556
thisMove.yAllowedDistance *= data.lastFrictionVertical;
15431557
// Fluidfalling(...). For water only, this is done after applying friction.
1544-
Vector fluidFallingAdjustMovement = from.getFluidFallingAdjustedMovement(data.lastGravity, lastMove.yAllowedDistance <= 0.0, new Vector(0.0, thisMove.yAllowedDistance, 0.0), cData.wasSprinting);
1558+
Vector fluidFallingAdjustMovement = from.getFluidFallingAdjustedMovement(data.lastGravity, thisMove.yAllowedDistance <= 0.0, new Vector(0.0, thisMove.yAllowedDistance, 0.0), cData.wasSprinting);
15451559
thisMove.yAllowedDistance = fluidFallingAdjustMovement.getY();
15461560
tags.add("v_water");
15471561
}
@@ -1587,6 +1601,10 @@ else if (lastMove.from.inLava) {
15871601
//////////////////////////////////
15881602
// Last client-tick/move //
15891603
//////////////////////////////////
1604+
if (from.isInLiquid() && verticalLiquidPushComponent != 0.0) {
1605+
// Liquid vertical push component calculated in hdistrel.
1606+
thisMove.yAllowedDistance += verticalLiquidPushComponent;
1607+
}
15901608
// *----------LivingEntity.aiStep(), negligible speed----------*
15911609
checkNegligibleMomentumVertical(pData, thisMove);
15921610
// *----------LivingEntity.travel(), handleRelativeFrictionAndCalculateMovement() -> handleOnClimbable()----------*

NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/location/RichEntityLocation.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,9 @@ else if (modLiquidHeight > 0.0f) {
866866
for (BlockFace hDirection : new BlockFace[]{BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST}) {
867867
if (BlockProperties.isSolidFace(blockCache, (Player) entity, x, y, z, hDirection, liquidTypeFlag, getLocation())
868868
|| BlockProperties.isSolidFace(blockCache, (Player) entity, x, y + 1, z, hDirection, liquidTypeFlag, getLocation())) {
869+
/*
870+
Vertical motion is modified here. Despite the function mostly being used for horizontal flow.
871+
*/
869872
flowingVector = MathUtil.normalizedVectorWithoutNaN(flowingVector).add(new Vector(0.0D, -6.0D, 0.0D));
870873
break;
871874
}

0 commit comments

Comments
 (0)