From 86397ef4836e2e716f910d210a1e5ebd8fdeec57 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 21 Mar 2021 11:31:09 -0400 Subject: [PATCH] Chunk cache improvements (#2053) - Check for minimum and maximum Y values to fix stack traces - Don't run half of the villager sleeping code unless they're actually sleeping --- .../connector/entity/FishingHookEntity.java | 42 ++++++------ .../living/merchant/VillagerEntity.java | 65 +++++++++---------- .../network/session/cache/ChunkCache.java | 11 ++++ 3 files changed, 62 insertions(+), 56 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java index 06e56ad03..0738c3819 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java @@ -96,27 +96,25 @@ public class FishingHookEntity extends ThrowableEntity { boolean touchingWater = false; boolean collided = false; for (Vector3i blockPos : collidableBlocks) { - if (0 <= blockPos.getY() && blockPos.getY() <= 255) { - int blockID = session.getConnector().getWorldManager().getBlockAt(session, blockPos); - BlockCollision blockCollision = CollisionTranslator.getCollision(blockID, blockPos.getX(), blockPos.getY(), blockPos.getZ()); - if (blockCollision != null && blockCollision.checkIntersection(boundingBox)) { - // TODO Push bounding box out of collision to improve movement - collided = true; - } + int blockID = session.getConnector().getWorldManager().getBlockAt(session, blockPos); + BlockCollision blockCollision = CollisionTranslator.getCollision(blockID, blockPos.getX(), blockPos.getY(), blockPos.getZ()); + if (blockCollision != null && blockCollision.checkIntersection(boundingBox)) { + // TODO Push bounding box out of collision to improve movement + collided = true; + } - int waterLevel = BlockStateValues.getWaterLevel(blockID); - if (BlockTranslator.isWaterlogged(blockID)) { - waterLevel = 0; + int waterLevel = BlockStateValues.getWaterLevel(blockID); + if (BlockTranslator.isWaterlogged(blockID)) { + waterLevel = 0; + } + if (waterLevel >= 0) { + double waterMaxY = blockPos.getY() + 1 - (waterLevel + 1) / 9.0; + // Falling water is a full block + if (waterLevel >= 8) { + waterMaxY = blockPos.getY() + 1; } - if (waterLevel >= 0) { - double waterMaxY = blockPos.getY() + 1 - (waterLevel + 1) / 9.0; - // Falling water is a full block - if (waterLevel >= 8) { - waterMaxY = blockPos.getY() + 1; - } - if (position.getY() <= waterMaxY) { - touchingWater = true; - } + if (position.getY() <= waterMaxY) { + touchingWater = true; } } } @@ -177,10 +175,8 @@ public class FishingHookEntity extends ThrowableEntity { */ protected boolean isInAir(GeyserSession session) { if (session.getConnector().getConfig().isCacheChunks()) { - if (0 <= position.getFloorY() && position.getFloorY() <= 255) { - int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt()); - return block == BlockTranslator.JAVA_AIR_ID; - } + int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt()); + return block == BlockTranslator.JAVA_AIR_ID; } return false; } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java index 56354774d..fa5785fe5 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java @@ -26,7 +26,6 @@ package org.geysermc.connector.entity.living.merchant; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; @@ -101,11 +100,17 @@ public class VillagerEntity extends AbstractMerchantEntity { @Override public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) { + if (!metadata.getFlags().getFlag(EntityFlag.SLEEPING)) { + // No need to worry about extra processing to compensate for sleeping + super.moveRelative(session, relX, relY, relZ, rotation, isOnGround); + return; + } + int z = 0; int bedId = 0; float bedPositionSubtractorW = 0; float bedPositionSubtractorN = 0; - Vector3i bedPosition = metadata.getPos(EntityData.BED_POSITION); + Vector3i bedPosition = metadata.getPos(EntityData.BED_POSITION, null); if (session.getConnector().getConfig().isCacheChunks() && bedPosition != null) { bedId = session.getConnector().getWorldManager().getBlockAt(session, bedPosition); } @@ -117,39 +122,33 @@ public class VillagerEntity extends AbstractMerchantEntity { MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); moveEntityPacket.setRuntimeEntityId(geyserId); //Sets Villager position and rotation when sleeping - if (!metadata.getFlags().getFlag(EntityFlag.SLEEPING)) { - moveEntityPacket.setPosition(position); - moveEntityPacket.setRotation(getBedrockRotation()); - } else { - //String Setup - Pattern r = Pattern.compile("facing=([a-z]+)"); - Matcher m = r.matcher(bedRotationZ); - if (m.find()) { - switch (m.group(0)) { - case "facing=south": - //bed is facing south - z = 180; - bedPositionSubtractorW = -.5f; - break; - case "facing=east": - //bed is facing east - z = 90; - bedPositionSubtractorW = -.5f; - break; - case "facing=west": - //bed is facing west - z = 270; - bedPositionSubtractorW = .5f; - break; - case "facing=north": - //rotation does not change because north is 0 - bedPositionSubtractorN = .5f; - break; - } + Pattern r = Pattern.compile("facing=([a-z]+)"); + Matcher m = r.matcher(bedRotationZ); + if (m.find()) { + switch (m.group(0)) { + case "facing=south": + //bed is facing south + z = 180; + bedPositionSubtractorW = -.5f; + break; + case "facing=east": + //bed is facing east + z = 90; + bedPositionSubtractorW = -.5f; + break; + case "facing=west": + //bed is facing west + z = 270; + bedPositionSubtractorW = .5f; + break; + case "facing=north": + //rotation does not change because north is 0 + bedPositionSubtractorN = .5f; + break; } - moveEntityPacket.setRotation(Vector3f.from(0, 0, z)); - moveEntityPacket.setPosition(Vector3f.from(position.getX() + bedPositionSubtractorW, position.getY(), position.getZ() + bedPositionSubtractorN)); } + moveEntityPacket.setRotation(Vector3f.from(0, 0, z)); + moveEntityPacket.setPosition(Vector3f.from(position.getX() + bedPositionSubtractorW, position.getY(), position.getZ() + bedPositionSubtractorN)); moveEntityPacket.setOnGround(isOnGround); moveEntityPacket.setTeleported(false); session.sendUpstreamPacket(moveEntityPacket); diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java index bf1f4718e..d182a6f12 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java @@ -34,6 +34,7 @@ import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.utils.MathUtils; public class ChunkCache { + private static final int MINIMUM_WORLD_HEIGHT = 0; private final boolean cache; @@ -86,6 +87,11 @@ public class ChunkCache { return; } + if (y < MINIMUM_WORLD_HEIGHT || (y >> 4) > column.getChunks().length - 1) { + // Y likely goes above or below the height limit of this world + return; + } + Chunk chunk = column.getChunks()[y >> 4]; if (chunk != null) { chunk.set(x & 0xF, y & 0xF, z & 0xF, block); @@ -102,6 +108,11 @@ public class ChunkCache { return BlockTranslator.JAVA_AIR_ID; } + if (y < MINIMUM_WORLD_HEIGHT || (y >> 4) > column.getChunks().length - 1) { + // Y likely goes above or below the height limit of this world + return BlockTranslator.JAVA_AIR_ID; + } + Chunk chunk = column.getChunks()[y >> 4]; if (chunk != null) { return chunk.get(x & 0xF, y & 0xF, z & 0xF);