Reduce velocity update rate (#1426)

This commit is contained in:
Arektor 2022-10-07 17:19:29 +02:00 committed by GitHub
parent 87c3dc3f76
commit 17ef1c2f57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 3 deletions

View File

@ -86,6 +86,8 @@ import java.util.function.UnaryOperator;
public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, EventHandler<EntityEvent>, Taggable, public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, EventHandler<EntityEvent>, Taggable,
PermissionHandler, HoverEventSource<ShowEntity>, Sound.Emitter { PermissionHandler, HoverEventSource<ShowEntity>, Sound.Emitter {
private static final int VELOCITY_UPDATE_INTERVAL = 1;
private static final Int2ObjectSyncMap<Entity> ENTITY_BY_ID = Int2ObjectSyncMap.hashmap(); private static final Int2ObjectSyncMap<Entity> ENTITY_BY_ID = Int2ObjectSyncMap.hashmap();
private static final Map<UUID, Entity> ENTITY_BY_UUID = new ConcurrentHashMap<>(); private static final Map<UUID, Entity> ENTITY_BY_UUID = new ConcurrentHashMap<>();
private static final AtomicInteger LAST_ENTITY_ID = new AtomicInteger(); private static final AtomicInteger LAST_ENTITY_ID = new AtomicInteger();
@ -106,6 +108,7 @@ public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, Ev
// Velocity // Velocity
protected Vec velocity = Vec.ZERO; // Movement in block per second protected Vec velocity = Vec.ZERO; // Movement in block per second
protected boolean lastVelocityWasZero = true;
protected boolean hasPhysics = true; protected boolean hasPhysics = true;
/** /**
@ -593,7 +596,12 @@ public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, Ev
-gravityAcceleration * tps * (1 - gravityDragPerTick), -gravityAcceleration * tps * (1 - gravityDragPerTick),
0 0
); );
if (!isPlayer) sendPacketToViewers(getVelocityPacket()); if (this.ticks % VELOCITY_UPDATE_INTERVAL == 0) {
if (!isPlayer && !this.lastVelocityWasZero) {
sendPacketToViewers(getVelocityPacket());
this.lastVelocityWasZero = !hasVelocity;
}
}
return; return;
} }
} }
@ -620,8 +628,11 @@ public class Entity implements Viewable, Tickable, Schedulable, Snapshotable, Ev
updateVelocity(wasOnGround, flying, positionBeforeMove, newVelocity); updateVelocity(wasOnGround, flying, positionBeforeMove, newVelocity);
} }
// Verify if velocity packet has to be sent // Verify if velocity packet has to be sent
if (!isPlayer && (hasVelocity || gravityTickCount > 0)) { if (this.ticks % VELOCITY_UPDATE_INTERVAL == 0) {
sendPacketToViewers(getVelocityPacket()); if (!isPlayer && (hasVelocity || !lastVelocityWasZero)) {
sendPacketToViewers(getVelocityPacket());
this.lastVelocityWasZero = !hasVelocity;
}
} }
} }

View File

@ -9,6 +9,9 @@ import net.minestom.server.network.packet.server.play.EntityVelocityPacket;
import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.chunk.ChunkUtils;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BooleanSupplier;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@EnvTest @EnvTest
@ -160,6 +163,30 @@ public class EntityVelocityIntegrationTest {
assertFalse(entity.hasVelocity()); assertFalse(entity.hasVelocity());
} }
@Test
public void countVelocityPackets(Env env) {
final int VELOCITY_UPDATE_INTERVAL = 1;
var instance = env.createFlatInstance();
var viewerConnection = env.createConnection();
viewerConnection.connect(instance, new Pos(1, 40, 1)).join();
var entity = new Entity(EntityType.ZOMBIE);
entity.setInstance(instance, new Pos(0,40,0)).join();
AtomicInteger i = new AtomicInteger();
BooleanSupplier tickLoopCondition = () -> i.getAndIncrement() < Math.max(VELOCITY_UPDATE_INTERVAL, 1);
var tracker = viewerConnection.trackIncoming(EntityVelocityPacket.class);
env.tickWhile(tickLoopCondition, null);
tracker.assertEmpty(); // Verify no updates are sent while the entity is not moving
entity.setVelocity(new Vec(0, 5, 0));
tracker = viewerConnection.trackIncoming(EntityVelocityPacket.class);
i.set(0);
env.tickWhile(tickLoopCondition, null);
tracker.assertCount(1); // Verify the update is only sent once
}
private void testMovement(Env env, Entity entity, Vec... sample) { private void testMovement(Env env, Entity entity, Vec... sample) {
final double epsilon = 0.003; final double epsilon = 0.003;
for (Vec vec : sample) { for (Vec vec : sample) {