Velocity cleanup

This commit is contained in:
Felix Cravic 2020-12-04 19:19:30 +01:00
parent 9b8579eaf4
commit cd44732cbc
2 changed files with 66 additions and 48 deletions

View File

@ -3,11 +3,13 @@ package net.minestom.server.collision;
import net.minestom.server.entity.Entity; import net.minestom.server.entity.Entity;
import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance; import net.minestom.server.instance.Instance;
import net.minestom.server.instance.WorldBorder;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.BlockPosition; import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position; import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector; import net.minestom.server.utils.Vector;
import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.chunk.ChunkUtils;
import org.jetbrains.annotations.NotNull;
public class CollisionUtils { public class CollisionUtils {
@ -172,4 +174,33 @@ public class CollisionUtils {
return true; return true;
} }
/**
* Applies world border collision.
*
* @param instance the instance where the world border is
* @param currentPosition the current position
* @param newPosition the future target position
* @return the position with the world border collision applied (can be {@code newPosition} if not changed)
*/
public static Position applyWorldBorder(@NotNull Instance instance,
@NotNull Position currentPosition, @NotNull Position newPosition) {
final WorldBorder worldBorder = instance.getWorldBorder();
final WorldBorder.CollisionAxis collisionAxis = worldBorder.getCollisionAxis(newPosition);
switch (collisionAxis) {
case NONE:
// Apply velocity + gravity
return newPosition;
case BOTH:
// Apply Y velocity/gravity
return new Position(currentPosition.getX(), newPosition.getY(), currentPosition.getZ());
case X:
// Apply Y/Z velocity/gravity
return new Position(currentPosition.getX(), newPosition.getY(), newPosition.getZ());
case Z:
// Apply X/Y velocity/gravity
return new Position(newPosition.getX(), newPosition.getY(), currentPosition.getZ());
}
throw new IllegalStateException("Something weird happened...");
}
} }

View File

@ -17,7 +17,6 @@ import net.minestom.server.event.handler.EventHandler;
import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance; import net.minestom.server.instance.Instance;
import net.minestom.server.instance.InstanceManager; import net.minestom.server.instance.InstanceManager;
import net.minestom.server.instance.WorldBorder;
import net.minestom.server.instance.block.CustomBlock; import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.network.packet.server.play.*; import net.minestom.server.network.packet.server.play.*;
import net.minestom.server.permission.Permission; import net.minestom.server.permission.Permission;
@ -469,10 +468,9 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
if (applyVelocity) { if (applyVelocity) {
final float tps = MinecraftServer.TICK_PER_SECOND; final float tps = MinecraftServer.TICK_PER_SECOND;
float newX = position.getX() + velocity.getX() / tps; final float newX = position.getX() + velocity.getX() / tps;
float newY = position.getY() + velocity.getY() / tps; final float newY = position.getY() + velocity.getY() / tps;
float newZ = position.getZ() + velocity.getZ() / tps; final float newZ = position.getZ() + velocity.getZ() / tps;
Position newPosition = new Position(newX, newY, newZ); Position newPosition = new Position(newX, newY, newZ);
if (!noGravity) { if (!noGravity) {
@ -487,63 +485,52 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
); );
this.onGround = CollisionUtils.handlePhysics(this, deltaPos, newPosition, newVelocityOut); this.onGround = CollisionUtils.handlePhysics(this, deltaPos, newPosition, newVelocityOut);
// Stop here if the position is the same
final boolean updatePosition = !newPosition.isSimilar(position);
// Check chunk // Check chunk
if (!ChunkUtils.isLoaded(instance, newPosition.getX(), newPosition.getZ())) { if (!ChunkUtils.isLoaded(instance, newPosition.getX(), newPosition.getZ())) {
return; return;
} }
// World border collision // World border and apply the position
final Position finalVelocityPosition = CollisionUtils.applyWorldBorder(instance, position, newPosition);
if (finalVelocityPosition != null && updatePosition) {
refreshPosition(finalVelocityPosition);
}
// Update velocity
{ {
final WorldBorder worldBorder = instance.getWorldBorder(); this.velocity.copy(newVelocityOut);
final WorldBorder.CollisionAxis collisionAxis = worldBorder.getCollisionAxis(newPosition); this.velocity.multiply(tps);
switch (collisionAxis) {
case NONE:
// Apply velocity + gravity
refreshPosition(newPosition);
break;
case BOTH:
// Apply Y velocity/gravity
refreshPosition(position.getX(), newPosition.getY(), position.getZ());
break;
case X:
// Apply Y/Z velocity/gravity
refreshPosition(position.getX(), newPosition.getY(), newPosition.getZ());
break;
case Z:
// Apply X/Y velocity/gravity
refreshPosition(newPosition.getX(), newPosition.getY(), position.getZ());
break;
}
}
this.velocity.copy(newVelocityOut); float drag;
this.velocity.multiply(tps); if (onGround) {
final BlockPosition blockPosition = position.toBlockPosition();
final CustomBlock customBlock = instance.getCustomBlock(blockPosition);
if (customBlock != null) {
// Custom drag
drag = customBlock.getDrag(instance, blockPosition);
} else {
// Default ground drag
drag = 0.5f;
}
float drag; // Stop player velocity
if (onGround) { if (PlayerUtils.isNettyClient(this)) {
final BlockPosition blockPosition = position.toBlockPosition(); velocity.zero();
final CustomBlock customBlock = instance.getCustomBlock(blockPosition); }
if (customBlock != null) {
// Custom drag
drag = customBlock.getDrag(instance, blockPosition);
} else { } else {
// Default ground drag drag = 0.98f; // air drag
drag = 0.5f;
} }
// Stop player velocity this.velocity.setX(velocity.getX() * drag);
if (PlayerUtils.isNettyClient(this)) { this.velocity.setZ(velocity.getZ() * drag);
velocity.zero();
}
} else {
drag = 0.98f; // air drag
} }
this.velocity.setX(velocity.getX() * drag); // Synchronization and packets...
this.velocity.setZ(velocity.getZ() * drag);
sendSynchronization(); sendSynchronization();
if (shouldSendVelocityUpdate(time)) { if (shouldSendVelocityUpdate(time)) {
sendVelocityPacket(); sendVelocityPacket();
lastVelocityUpdateTime = time; lastVelocityUpdateTime = time;