mirror of
https://hub.spigotmc.org/stash/scm/spigot/spigot.git
synced 2025-09-18 21:33:01 +00:00
Rewrite minecraft's movement handling to move it into the main tick loop
This commit is contained in:
parent
0b49f96812
commit
5fb051b619
1 changed files with 421 additions and 0 deletions
|
@ -0,0 +1,421 @@
|
|||
From d522552c015ee9437dabb05d05e59c276ecdca43 Mon Sep 17 00:00:00 2001
|
||||
From: Thinkofdeath <thinkofdeath@spigotmc.org>
|
||||
Date: Fri, 4 Jul 2014 09:50:02 +0100
|
||||
Subject: [PATCH] Move player ticking into the main loop
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
index de20c6a..108552e 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
@@ -175,7 +175,17 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
||||
return 1.62F;
|
||||
}
|
||||
|
||||
+ // Spigot start
|
||||
+ private AxisAlignedBB groundCheck = AxisAlignedBB.a( 0, 0, 0, 0, 0, 0 );
|
||||
+ public double stance;
|
||||
+ private int offGroundTicks = 0;
|
||||
+ private int moveHelper = 1;
|
||||
+ private long lastMovementTick = System.nanoTime();
|
||||
+
|
||||
public void h() {
|
||||
+ validateMovement();
|
||||
+ // Spigot end
|
||||
+
|
||||
// CraftBukkit start
|
||||
if (this.joining) {
|
||||
this.joining = false;
|
||||
@@ -254,8 +264,230 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
||||
if (this.bX > 0L && this.server.getIdleTimeout() > 0 && MinecraftServer.ar() - this.bX > (long) (this.server.getIdleTimeout() * 1000 * 60)) {
|
||||
this.playerConnection.disconnect("You have been idle for too long!");
|
||||
}
|
||||
+ // Spigot start
|
||||
+ this.i();
|
||||
+ }
|
||||
+
|
||||
+ private void validateMovement()
|
||||
+ {
|
||||
+ long currentTime = System.nanoTime();
|
||||
+ if ( !playerConnection.checkMovement )
|
||||
+ {
|
||||
+ double diffX = Math.abs( locX - lastX );
|
||||
+ double diffY = Math.abs( locY - lastY );
|
||||
+ double diffZ = Math.abs( locZ - lastZ );
|
||||
+ if ( diffX < 0.01 && diffY < 0.01 && diffZ < 0.01 )
|
||||
+ {
|
||||
+ playerConnection.checkMovement = true;
|
||||
+ } else
|
||||
+ {
|
||||
+ playerConnection.a( lastX, lastY, lastZ, lastYaw, lastPitch );
|
||||
+ }
|
||||
+ MinecraftServer.getServer().getPlayerList().d( this );
|
||||
+ }
|
||||
+ if ( !dead && playerConnection.checkMovement )
|
||||
+ {
|
||||
+
|
||||
+ double diffX = locX - lastX;
|
||||
+ double diffY = locY - lastY;
|
||||
+ double diffZ = locZ - lastZ;
|
||||
+
|
||||
+ if ( diffX != 0 || diffY != 0 || diffZ != 0 )
|
||||
+ {
|
||||
+ // Can't move while sleeping
|
||||
+ if ( isSleeping() )
|
||||
+ {
|
||||
+ setLocation( lastX, lastY, lastZ, lastYaw, lastPitch );
|
||||
+ lastMovementTick = currentTime;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // Vehicle handling
|
||||
+ if ( vehicle != null )
|
||||
+ {
|
||||
+ float f = yaw;
|
||||
+ float f1 = pitch;
|
||||
+
|
||||
+ vehicle.ab();
|
||||
+ double d1 = locX;
|
||||
+ double d2 = locY;
|
||||
+ double d3 = locZ;
|
||||
+
|
||||
+ V = 0.0F;
|
||||
+ setLocation( d1, d2, d3, f, f1 );
|
||||
+ if ( vehicle != null )
|
||||
+ {
|
||||
+ vehicle.ab();
|
||||
+ }
|
||||
+
|
||||
+ MinecraftServer.getServer().getPlayerList().d( this );
|
||||
+ lastMovementTick = currentTime;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ AxisAlignedBB newBounds = boundingBox.clone().c( diffX, diffY, diffZ ).shrink( 0.01, 0.01, 0.01 );
|
||||
+ if ( !world.getCubes( this, newBounds ).isEmpty() )
|
||||
+ {
|
||||
+ playerConnection.a( lastX, lastY, lastZ, lastYaw, lastPitch );
|
||||
+ lastMovementTick = currentTime;
|
||||
+ return;
|
||||
+ }
|
||||
+ newBounds.grow( 0.01, 0.01, 0.01 );
|
||||
+
|
||||
+ // Speed checks
|
||||
+
|
||||
+ double moveX = Math.max( Math.abs( diffX ), Math.abs( motX ) );
|
||||
+ double moveY = Math.max( Math.abs( diffY ), Math.abs( motY ) );
|
||||
+ double moveZ = Math.max( Math.abs( diffZ ), Math.abs( motZ ) );
|
||||
+ double totalMovement = moveX * moveX + moveY * moveY + moveZ * moveZ;
|
||||
+
|
||||
+ double limit = 100.0 * Math.max( 1.0, (currentTime - lastMovementTick) / 50000000.0);
|
||||
+ if ( totalMovement > limit )
|
||||
+ {
|
||||
+ bL.warn( getName() + " moved too quickly! " + diffX + "," + diffY + "," + diffZ + " (" + moveX + ", " + moveY + ", " + moveZ + ") with a limit of " + limit );
|
||||
+ playerConnection.a( lastX, lastY, lastZ, lastYaw, lastPitch );
|
||||
+ lastMovementTick = currentTime;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ groundCheck.b( locX - 0.3, locY - 0.1, locZ - 0.3, locX + 0.3, locY, locZ + 0.3 );
|
||||
+ onGround = !world.getCubes( this, groundCheck ).isEmpty();
|
||||
+ if (!onGround && diffY < 0) {
|
||||
+ groundCheck.b( locX - 0.3, locY - 0.25, locZ - 0.3, locX + 0.3, locY, locZ + 0.3 );
|
||||
+ onGround = !world.getCubes( this, groundCheck ).isEmpty();
|
||||
+ if (onGround) {
|
||||
+ fallDistance += 0.1; // Account for client 'hover'
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Fly detection
|
||||
+ if ( !onGround && !MinecraftServer.getServer().getAllowFlight() && !abilities.canFly
|
||||
+ && diffY >= -0.03125D )
|
||||
+ {
|
||||
+ offGroundTicks++;
|
||||
+ if ( offGroundTicks > 80 )
|
||||
+ {
|
||||
+ bL.warn( getName() + " was kicked for floating too long!" );
|
||||
+ playerConnection.disconnect( "Flying is not enabled on this server" );
|
||||
+ return;
|
||||
+ }
|
||||
+ } else
|
||||
+ {
|
||||
+ offGroundTicks = 0;
|
||||
+ }
|
||||
+
|
||||
+ // Block interactions
|
||||
+
|
||||
+ boolean isTouching = this.onGround && this.isSneaking();
|
||||
+ double diffY1 = diffY;
|
||||
+
|
||||
+ if ( this.g_() && !isTouching && this.vehicle == null )
|
||||
+ {
|
||||
+ int l = MathHelper.floor( this.locX );
|
||||
+
|
||||
+ int k = MathHelper.floor( this.locY - 0.20000000298023224D - (double) this.height );
|
||||
+ int i1 = MathHelper.floor( this.locZ );
|
||||
+ Block block = this.world.getType( l, k, i1 );
|
||||
+ int j1 = this.world.getType( l, k - 1, i1 ).b();
|
||||
+
|
||||
+ if ( j1 == 11 || j1 == 32 || j1 == 21 )
|
||||
+ {
|
||||
+ block = this.world.getType( l, k - 1, i1 );
|
||||
+ }
|
||||
+
|
||||
+ if ( block != Blocks.LADDER )
|
||||
+ {
|
||||
+ diffY1 = 0.0D;
|
||||
+ }
|
||||
+
|
||||
+ this.P = (float) ( (double) this.P + (double) MathHelper.sqrt( diffX * diffX + diffZ * diffZ ) * 0.6D );
|
||||
+ this.Q = (float) ( (double) this.Q + (double) MathHelper.sqrt( diffX * diffX + diffY1 * diffY1 + diffZ * diffZ ) * 0.6D );
|
||||
+ if ( this.Q > (float) this.moveHelper && block.getMaterial() != Material.AIR )
|
||||
+ {
|
||||
+ this.moveHelper = (int) this.Q + 1;
|
||||
+ if ( this.L() )
|
||||
+ {
|
||||
+ float f = MathHelper.sqrt( this.motX * this.motX * 0.20000000298023224D + this.motY * this.motY + this.motZ * this.motZ * 0.20000000298023224D ) * 0.35F;
|
||||
+
|
||||
+ if ( f > 1.0F )
|
||||
+ {
|
||||
+ f = 1.0F;
|
||||
+ }
|
||||
+
|
||||
+ this.makeSound( this.G(), f, 1.0F + ( this.random.nextFloat() - this.random.nextFloat() ) * 0.4F );
|
||||
+ }
|
||||
+
|
||||
+ this.a( l, k, i1, block );
|
||||
+ block.b( this.world, l, k, i1, this );
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Fire damage
|
||||
+
|
||||
+ boolean isWet = this.K();
|
||||
+
|
||||
+ if ( this.world.e( newBounds ) )
|
||||
+ {
|
||||
+ this.burn( 1 );
|
||||
+ if ( !isWet )
|
||||
+ {
|
||||
+ ++this.fireTicks;
|
||||
+ // CraftBukkit start - Not on fire yet
|
||||
+ if ( this.fireTicks <= 0 )
|
||||
+ { // Only throw events on the first combust, otherwise it spams
|
||||
+ org.bukkit.event.entity.EntityCombustEvent event = new org.bukkit.event.entity.EntityCombustEvent( this.getBukkitEntity(), 8 );
|
||||
+ this.world.getServer().getPluginManager().callEvent( event );
|
||||
+
|
||||
+ if ( !event.isCancelled() )
|
||||
+ {
|
||||
+ this.setOnFire( event.getDuration() );
|
||||
+ }
|
||||
+ } else
|
||||
+ {
|
||||
+ // CraftBukkit end
|
||||
+ this.setOnFire( 8 );
|
||||
+ }
|
||||
+ }
|
||||
+ } else if ( this.fireTicks <= 0 )
|
||||
+ {
|
||||
+ this.fireTicks = -this.maxFireTicks;
|
||||
+ }
|
||||
+
|
||||
+ if ( isWet && this.fireTicks > 0 )
|
||||
+ {
|
||||
+ this.makeSound( "random.fizz", 0.7F, 1.6F + ( this.random.nextFloat() - this.random.nextFloat() ) * 0.4F );
|
||||
+ this.fireTicks = -this.maxFireTicks;
|
||||
+ }
|
||||
+
|
||||
+ this.b( locY - lastY, onGround );
|
||||
+ checkMovement( diffX, diffY, diffZ );
|
||||
+ setLocation( locX, locY, locZ, yaw, pitch );
|
||||
+ MinecraftServer.getServer().getPlayerList().d( this );
|
||||
+ }
|
||||
+
|
||||
+ // Block collisions
|
||||
+ try
|
||||
+ {
|
||||
+ this.H();
|
||||
+ } catch ( Throwable throwable )
|
||||
+ {
|
||||
+ CrashReport crashreport = CrashReport.a( throwable, "Checking entity block collision" );
|
||||
+ CrashReportSystemDetails crashreportsystemdetails = crashreport.a( "Entity being checked for collision" );
|
||||
+
|
||||
+ this.a( crashreportsystemdetails );
|
||||
+ throw new ReportedException( crashreport );
|
||||
+ }
|
||||
+ }
|
||||
+ lastMovementTick = currentTime;
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public void move(double d0, double d1, double d2)
|
||||
+ {
|
||||
+ }
|
||||
+
|
||||
+ // Spigot end
|
||||
+
|
||||
public void i() {
|
||||
try {
|
||||
super.h();
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
|
||||
index 1221319..7266c39 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
|
||||
@@ -105,7 +105,7 @@ public class PlayerConnection implements PacketPlayInListener {
|
||||
private double lastPosZ = Double.MAX_VALUE;
|
||||
private float lastPitch = Float.MAX_VALUE;
|
||||
private float lastYaw = Float.MAX_VALUE;
|
||||
- private boolean justTeleported = false;
|
||||
+ public boolean justTeleported = false; // Spigot
|
||||
private boolean hasMoved; // Spigot
|
||||
|
||||
// For the PacketPlayOutBlockPlace hack :(
|
||||
@@ -180,13 +180,129 @@ public class PlayerConnection implements PacketPlayInListener {
|
||||
this.player.a(packetplayinsteervehicle.c(), packetplayinsteervehicle.d(), packetplayinsteervehicle.e(), packetplayinsteervehicle.f());
|
||||
}
|
||||
|
||||
- public void a(PacketPlayInFlying packetplayinflying) {
|
||||
+ public void a(PacketPlayInFlying packetplayinflying)
|
||||
+ {
|
||||
// CraftBukkit start - Check for NaN
|
||||
- if (Double.isNaN(packetplayinflying.x) || Double.isNaN(packetplayinflying.y) || Double.isNaN(packetplayinflying.z) || Double.isNaN(packetplayinflying.stance)) {
|
||||
- c.warn(player.getName() + " was caught trying to crash the server with an invalid position.");
|
||||
- getPlayer().kickPlayer("NaN in position (Hacking?)"); //Spigot "Nope" -> Descriptive reason
|
||||
+ if ( Double.isNaN( packetplayinflying.x ) || Double.isNaN( packetplayinflying.y ) || Double.isNaN( packetplayinflying.z ) || Double.isNaN( packetplayinflying.stance ) )
|
||||
+ {
|
||||
+ c.warn( player.getName() + " was caught trying to crash the server with an invalid position." );
|
||||
+ getPlayer().kickPlayer( "NaN in position (Hacking?)" ); //Spigot "Nope" -> Descriptive reason
|
||||
+ return;
|
||||
+ }
|
||||
+ // Spigot start
|
||||
+ if ( packetplayinflying.hasPos )
|
||||
+ {
|
||||
+ if (Math.abs(packetplayinflying.c()) > 3.2E7D || Math.abs(packetplayinflying.e()) > 3.2E7D) {
|
||||
+ this.disconnect("Illegal position");
|
||||
+ return;
|
||||
+ }
|
||||
+ player.locX = packetplayinflying.x;
|
||||
+ player.locY = packetplayinflying.y;
|
||||
+ player.stance = packetplayinflying.stance;
|
||||
+ player.locZ = packetplayinflying.z;
|
||||
+ }
|
||||
+ if ( packetplayinflying.hasLook )
|
||||
+ {
|
||||
+ player.yaw = packetplayinflying.yaw;
|
||||
+ player.pitch = packetplayinflying.pitch;
|
||||
+ }
|
||||
+
|
||||
+ double d4 = player.lastX - this.player.locX;
|
||||
+ double d5 = player.lastY - this.player.locY;
|
||||
+ double d6 = player.lastZ - this.player.locZ;
|
||||
+ // CraftBukkit start - min to max
|
||||
+ double d7 = Math.max(Math.abs(d4), Math.abs(this.player.motX));
|
||||
+ double d8 = Math.max(Math.abs(d5), Math.abs(this.player.motY));
|
||||
+ double d9 = Math.max(Math.abs(d6), Math.abs(this.player.motZ));
|
||||
+ // CraftBukkit end
|
||||
+ double d10 = d7 * d7 + d8 * d8 + d9 * d9;
|
||||
+
|
||||
+ if (d10 > 100.0D && this.checkMovement && (!this.minecraftServer.N() || !this.minecraftServer.M().equals(this.player.getName()))) { // CraftBukkit - Added this.checkMovement condition to solve this check being triggered by teleports
|
||||
+ c.warn(this.player.getName() + " moved too quickly! " + d4 + "," + d5 + "," + d6 + " (" + d7 + ", " + d8 + ", " + d9 + ")");
|
||||
+ this.a(this.y, this.z, this.q, this.player.yaw, this.player.pitch);
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start - fire PlayerMoveEvent
|
||||
+ Player player = this.getPlayer();
|
||||
+ // Spigot Start
|
||||
+ if ( !hasMoved )
|
||||
+ {
|
||||
+ Location curPos = player.getLocation();
|
||||
+ lastPosX = curPos.getX();
|
||||
+ lastPosY = curPos.getY();
|
||||
+ lastPosZ = curPos.getZ();
|
||||
+ lastYaw = curPos.getYaw();
|
||||
+ lastPitch = curPos.getPitch();
|
||||
+ hasMoved = true;
|
||||
+ }
|
||||
+ // Spigot End
|
||||
+ Location from = new Location( player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch ); // Get the Players previous Event location.
|
||||
+ Location to = player.getLocation().clone(); // Start off the To location as the Players current location.
|
||||
+
|
||||
+ // If the packet contains movement information then we update the To location with the correct XYZ.
|
||||
+ if ( packetplayinflying.hasPos && !( packetplayinflying.hasPos && packetplayinflying.y == -999.0D && packetplayinflying.stance == -999.0D ) )
|
||||
+ {
|
||||
+ to.setX( packetplayinflying.x );
|
||||
+ to.setY( packetplayinflying.y );
|
||||
+ to.setZ( packetplayinflying.z );
|
||||
+ }
|
||||
+
|
||||
+ // If the packet contains look information then we update the To location with the correct Yaw & Pitch.
|
||||
+ if ( packetplayinflying.hasLook )
|
||||
+ {
|
||||
+ to.setYaw( packetplayinflying.yaw );
|
||||
+ to.setPitch( packetplayinflying.pitch );
|
||||
+ }
|
||||
+
|
||||
+ // Prevent 40 event-calls for less than a single pixel of movement >.>
|
||||
+ double delta = Math.pow( this.lastPosX - to.getX(), 2 ) + Math.pow( this.lastPosY - to.getY(), 2 ) + Math.pow( this.lastPosZ - to.getZ(), 2 );
|
||||
+ float deltaAngle = Math.abs( this.lastYaw - to.getYaw() ) + Math.abs( this.lastPitch - to.getPitch() );
|
||||
+
|
||||
+ if ( ( delta > 1f / 256 || deltaAngle > 10f ) && ( this.checkMovement && !this.player.dead ) )
|
||||
+ {
|
||||
+ this.lastPosX = to.getX();
|
||||
+ this.lastPosY = to.getY();
|
||||
+ this.lastPosZ = to.getZ();
|
||||
+ this.lastYaw = to.getYaw();
|
||||
+ this.lastPitch = to.getPitch();
|
||||
+
|
||||
+ // Skip the first time we do this
|
||||
+ if ( true )
|
||||
+ { // Spigot - don't skip any move events
|
||||
+ PlayerMoveEvent event = new PlayerMoveEvent( player, from, to );
|
||||
+ this.server.getPluginManager().callEvent( event );
|
||||
+
|
||||
+ // If the event is cancelled we move the player back to their old location.
|
||||
+ if ( event.isCancelled() )
|
||||
+ {
|
||||
+ this.player.playerConnection.sendPacket( new PacketPlayOutPosition( from.getX(), from.getY() + 1.6200000047683716D, from.getZ(), from.getYaw(), from.getPitch(), false ) );
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* If a Plugin has changed the To destination then we teleport the Player
|
||||
+ there to avoid any 'Moved wrongly' or 'Moved too quickly' errors.
|
||||
+ We only do this if the Event was not cancelled. */
|
||||
+ if ( !to.equals( event.getTo() ) && !event.isCancelled() )
|
||||
+ {
|
||||
+ this.player.getBukkitEntity().teleport( event.getTo(), PlayerTeleportEvent.TeleportCause.UNKNOWN );
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Check to see if the Players Location has some how changed during the call of the event.
|
||||
+ This can happen due to a plugin teleporting the player instead of using .setTo() */
|
||||
+ if ( !from.equals( this.getPlayer().getLocation() ) && this.justTeleported )
|
||||
+ {
|
||||
+ this.justTeleported = false;
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ private void noop(PacketPlayInFlying packetplayinflying) {
|
||||
+ // Spigot end
|
||||
// CraftBukkit end
|
||||
WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension);
|
||||
|
||||
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
|
||||
index 06284ad..a2f1010 100644
|
||||
--- a/src/main/java/org/spigotmc/ActivationRange.java
|
||||
+++ b/src/main/java/org/spigotmc/ActivationRange.java
|
||||
@@ -262,6 +262,7 @@ public class ActivationRange
|
||||
*/
|
||||
public static boolean checkIfActive(Entity entity)
|
||||
{
|
||||
+ if ( entity instanceof net.minecraft.server.EntityPlayer ) return true;
|
||||
SpigotTimings.checkIfActiveTimer.startTiming();
|
||||
boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState;
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
Loading…
Add table
Reference in a new issue