mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Prevent large ArrayLists from growing on collision checks
See #2540 - not confirmed to be resolved as we weren't able to replicate a cause for this issue but this solved the issue from artifically invoking it.
This commit is contained in:
parent
d5c37e927b
commit
c28364c5dd
4 changed files with 19 additions and 12 deletions
|
@ -929,7 +929,7 @@ public class GeyserSession implements CommandSender {
|
||||||
// Check to see if the player's position needs updating - a position update should be sent once every 3 seconds
|
// Check to see if the player's position needs updating - a position update should be sent once every 3 seconds
|
||||||
if (spawned && (System.currentTimeMillis() - lastMovementTimestamp) > 3000) {
|
if (spawned && (System.currentTimeMillis() - lastMovementTimestamp) > 3000) {
|
||||||
// Recalculate in case something else changed position
|
// Recalculate in case something else changed position
|
||||||
Vector3d position = collisionManager.adjustBedrockPosition(playerEntity.getPosition(), playerEntity.isOnGround());
|
Vector3d position = collisionManager.adjustBedrockPosition(playerEntity.getPosition(), playerEntity.isOnGround(), false);
|
||||||
// A null return value cancels the packet
|
// A null return value cancels the packet
|
||||||
if (position != null) {
|
if (position != null) {
|
||||||
ClientPlayerPositionPacket packet = new ClientPlayerPositionPacket(playerEntity.isOnGround(),
|
ClientPlayerPositionPacket packet = new ClientPlayerPositionPacket(playerEntity.isOnGround(),
|
||||||
|
|
|
@ -150,7 +150,7 @@ public class PistonCache {
|
||||||
|
|
||||||
Vector3d delta = totalDisplacement.sub(playerDisplacement);
|
Vector3d delta = totalDisplacement.sub(playerDisplacement);
|
||||||
// Check if the piston is pushing a player into collision
|
// Check if the piston is pushing a player into collision
|
||||||
delta = session.getCollisionManager().correctPlayerMovement(delta, true);
|
delta = session.getCollisionManager().correctPlayerMovement(delta, true, false);
|
||||||
|
|
||||||
session.getCollisionManager().getPlayerBoundingBox().translate(delta.getX(), delta.getY(), delta.getZ());
|
session.getCollisionManager().getPlayerBoundingBox().translate(delta.getX(), delta.getY(), delta.getZ());
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isValidMove(session, packet.getMode(), entity.getPosition(), packet.getPosition())) {
|
if (isValidMove(session, packet.getMode(), entity.getPosition(), packet.getPosition())) {
|
||||||
Vector3d position = session.getCollisionManager().adjustBedrockPosition(packet.getPosition(), packet.isOnGround());
|
Vector3d position = session.getCollisionManager().adjustBedrockPosition(packet.getPosition(), packet.isOnGround(), packet.getMode() == MovePlayerPacket.Mode.TELEPORT);
|
||||||
if (position != null) { // A null return value cancels the packet
|
if (position != null) { // A null return value cancels the packet
|
||||||
Packet movePacket;
|
Packet movePacket;
|
||||||
if (rotationChanged) {
|
if (rotationChanged) {
|
||||||
|
|
|
@ -135,7 +135,7 @@ public class CollisionManager {
|
||||||
* @param onGround whether the Bedrock player is on the ground
|
* @param onGround whether the Bedrock player is on the ground
|
||||||
* @return the position to send to the Java server, or null to cancel sending the packet
|
* @return the position to send to the Java server, or null to cancel sending the packet
|
||||||
*/
|
*/
|
||||||
public Vector3d adjustBedrockPosition(Vector3f bedrockPosition, boolean onGround) {
|
public Vector3d adjustBedrockPosition(Vector3f bedrockPosition, boolean onGround, boolean teleported) {
|
||||||
PistonCache pistonCache = session.getPistonCache();
|
PistonCache pistonCache = session.getPistonCache();
|
||||||
// Bedrock clients tend to fall off of honey blocks, so we need to teleport them to the new position
|
// Bedrock clients tend to fall off of honey blocks, so we need to teleport them to the new position
|
||||||
if (pistonCache.isPlayerAttachedToHoney()) {
|
if (pistonCache.isPlayerAttachedToHoney()) {
|
||||||
|
@ -150,7 +150,7 @@ public class CollisionManager {
|
||||||
|
|
||||||
Vector3d startingPos = playerBoundingBox.getBottomCenter();
|
Vector3d startingPos = playerBoundingBox.getBottomCenter();
|
||||||
Vector3d movement = position.sub(startingPos);
|
Vector3d movement = position.sub(startingPos);
|
||||||
Vector3d adjustedMovement = correctPlayerMovement(movement, false);
|
Vector3d adjustedMovement = correctPlayerMovement(movement, false, teleported);
|
||||||
playerBoundingBox.translate(adjustedMovement.getX(), adjustedMovement.getY(), adjustedMovement.getZ());
|
playerBoundingBox.translate(adjustedMovement.getX(), adjustedMovement.getY(), adjustedMovement.getZ());
|
||||||
playerBoundingBox.translate(pistonCache.getPlayerMotion().getX(), pistonCache.getPlayerMotion().getY(), pistonCache.getPlayerMotion().getZ());
|
playerBoundingBox.translate(pistonCache.getPlayerMotion().getX(), pistonCache.getPlayerMotion().getY(), pistonCache.getPlayerMotion().getZ());
|
||||||
// Correct player position
|
// Correct player position
|
||||||
|
@ -211,17 +211,22 @@ public class CollisionManager {
|
||||||
// Expand volume by 1 in each direction to include moving blocks
|
// Expand volume by 1 in each direction to include moving blocks
|
||||||
double pistonExpand = session.getPistonCache().getPistons().isEmpty() ? 0 : 1;
|
double pistonExpand = session.getPistonCache().getPistons().isEmpty() ? 0 : 1;
|
||||||
|
|
||||||
|
// Ensure sizes cannot be too large - https://github.com/GeyserMC/Geyser/issues/2540
|
||||||
|
double sizeX = Math.min(box.getSizeX(), 256);
|
||||||
|
double sizeY = Math.min(box.getSizeY(), 256);
|
||||||
|
double sizeZ = Math.min(box.getSizeZ(), 256);
|
||||||
|
|
||||||
// Loop through all blocks that could collide
|
// Loop through all blocks that could collide
|
||||||
int minCollisionX = (int) Math.floor(position.getX() - ((box.getSizeX() / 2) + COLLISION_TOLERANCE + pistonExpand));
|
int minCollisionX = (int) Math.floor(position.getX() - ((sizeX / 2) + COLLISION_TOLERANCE + pistonExpand));
|
||||||
int maxCollisionX = (int) Math.floor(position.getX() + (box.getSizeX() / 2) + COLLISION_TOLERANCE + pistonExpand);
|
int maxCollisionX = (int) Math.floor(position.getX() + (sizeX / 2) + COLLISION_TOLERANCE + pistonExpand);
|
||||||
|
|
||||||
// Y extends 0.5 blocks down because of fence hitboxes
|
// Y extends 0.5 blocks down because of fence hitboxes
|
||||||
int minCollisionY = (int) Math.floor(position.getY() - 0.5 - COLLISION_TOLERANCE - pistonExpand / 2.0);
|
int minCollisionY = (int) Math.floor(position.getY() - 0.5 - COLLISION_TOLERANCE - pistonExpand / 2.0);
|
||||||
|
|
||||||
int maxCollisionY = (int) Math.floor(position.getY() + box.getSizeY() + pistonExpand);
|
int maxCollisionY = (int) Math.floor(position.getY() + sizeY + pistonExpand);
|
||||||
|
|
||||||
int minCollisionZ = (int) Math.floor(position.getZ() - ((box.getSizeZ() / 2) + COLLISION_TOLERANCE + pistonExpand));
|
int minCollisionZ = (int) Math.floor(position.getZ() - ((sizeZ / 2) + COLLISION_TOLERANCE + pistonExpand));
|
||||||
int maxCollisionZ = (int) Math.floor(position.getZ() + (box.getSizeZ() / 2) + COLLISION_TOLERANCE + pistonExpand);
|
int maxCollisionZ = (int) Math.floor(position.getZ() + (sizeZ / 2) + COLLISION_TOLERANCE + pistonExpand);
|
||||||
|
|
||||||
for (int y = minCollisionY; y < maxCollisionY + 1; y++) {
|
for (int y = minCollisionY; y < maxCollisionY + 1; y++) {
|
||||||
for (int x = minCollisionX; x < maxCollisionX + 1; x++) {
|
for (int x = minCollisionX; x < maxCollisionX + 1; x++) {
|
||||||
|
@ -276,8 +281,10 @@ public class CollisionManager {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3d correctPlayerMovement(Vector3d movement, boolean checkWorld) {
|
public Vector3d correctPlayerMovement(Vector3d movement, boolean checkWorld, boolean teleported) {
|
||||||
if (!checkWorld && session.getPistonCache().getPistons().isEmpty()) { // There is nothing to check
|
// On the teleported check: see https://github.com/GeyserMC/Geyser/issues/2540
|
||||||
|
// As of this commit we don't know how it happens but we don't need to check movement here anyway in that case
|
||||||
|
if (teleported || (!checkWorld && session.getPistonCache().getPistons().isEmpty())) { // There is nothing to check
|
||||||
return movement;
|
return movement;
|
||||||
}
|
}
|
||||||
return correctMovement(movement, playerBoundingBox, session.getPlayerEntity().isOnGround(), PLAYER_STEP_UP, checkWorld);
|
return correctMovement(movement, playerBoundingBox, session.getPlayerEntity().isOnGround(), PLAYER_STEP_UP, checkWorld);
|
||||||
|
|
Loading…
Reference in a new issue