From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Samsuik Date: Sat, 11 Sep 2021 19:19:41 +0100 Subject: [PATCH] Load Chunks on Movement diff --git a/src/main/java/io/papermc/paper/util/CollisionUtil.java b/src/main/java/io/papermc/paper/util/CollisionUtil.java index ee0331a6bc40cdde08d926fd8eb1dc642630c2e5..19086bbfdf3a015eafec5ca868c8d2451f554ef0 100644 --- a/src/main/java/io/papermc/paper/util/CollisionUtil.java +++ b/src/main/java/io/papermc/paper/util/CollisionUtil.java @@ -1569,6 +1569,7 @@ public final class CollisionUtil { public static final int COLLISION_FLAG_COLLIDE_WITH_UNLOADED_CHUNKS = 1 << 1; public static final int COLLISION_FLAG_CHECK_BORDER = 1 << 2; public static final int COLLISION_FLAG_CHECK_ONLY = 1 << 3; + public static final int COLLISION_FLAG_ADD_TICKET = 1 << 4; // Sakura public static boolean getCollisionsForBlocksOrWorldBorder(final Level world, final Entity entity, final AABB aabb, final List intoVoxel, final List intoAABB, @@ -1619,11 +1620,21 @@ public final class CollisionUtil { final int maxChunkZ = maxBlockZ >> 4; final boolean loadChunks = (collisionFlags & COLLISION_FLAG_LOAD_CHUNKS) != 0; + final boolean addTicket = (collisionFlags & COLLISION_FLAG_ADD_TICKET) != 0; // Sakura final ServerChunkCache chunkSource = (ServerChunkCache)world.getChunkSource(); for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) { for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) { final ChunkAccess chunk = loadChunks ? chunkSource.getChunk(currChunkX, currChunkZ, ChunkStatus.FULL, true) : chunkSource.getChunkAtIfLoadedImmediately(currChunkX, currChunkZ); + // Sakura start - keep chunks loaded on movement + if (addTicket && chunk instanceof net.minecraft.world.level.chunk.LevelChunk levelChunk && levelChunk.movementLoadTicketRequiresUpdate()) { + chunkSource.chunkMap.getDistanceManager().getChunkHolderManager().addTicketAtLevel(net.minecraft.server.level.TicketType.ENTITY_MOVEMENT, currChunkX, currChunkZ, 33, CoordinateUtils.getChunkKey(currChunkX, currChunkZ)); + // This is known to work, uncomment if any issues + // var pos = new net.minecraft.world.level.ChunkPos(currChunkX, currChunkZ); + // chunkSource.addTicketAtLevel(net.minecraft.server.level.TicketType.ENTITY_MOVEMENT, pos, 33, pos.toLong()); + levelChunk.updatedMovementLoadTicket(); + } + // Sakura end if (chunk == null) { if ((collisionFlags & COLLISION_FLAG_COLLIDE_WITH_UNLOADED_CHUNKS) != 0) { diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java index 658e63ebde81dc14c8ab5850fb246dc0aab25dea..f1ff1a67fee37ee7b241ceaa164fa4ee64d3767b 100644 --- a/src/main/java/net/minecraft/server/level/TicketType.java +++ b/src/main/java/net/minecraft/server/level/TicketType.java @@ -37,6 +37,7 @@ public class TicketType { public static final TicketType NON_FULL_SYNC_LOAD = create("non_full_sync_load", Long::compareTo); public static final TicketType DELAY_UNLOAD = create("delay_unload", Comparator.comparingLong(ChunkPos::toLong), 1); // Paper end - rewrite chunk system + public static final TicketType ENTITY_MOVEMENT = create("entity_movement", Long::compareTo, 10 * 20); // Sakura public static TicketType create(String name, Comparator argumentComparator) { return new TicketType<>(name, argumentComparator, 0L); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index 4ffa96f7eeefd6a2a07458f68458cdbf4369340f..583f94cd4f517f17909da43f546e8c9e4580d3ad 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -537,6 +537,19 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S // Paper end - make end portalling safe public boolean isPrimedTNT; // Sakura public boolean isFallingBlock; // Sakura + // Sakura start + protected boolean loadChunks = false; + + private int getExtraCollisionFlags() { + int flags = 0; + + if (this.loadChunks) { + flags |= io.papermc.paper.util.CollisionUtil.COLLISION_FLAG_LOAD_CHUNKS | io.papermc.paper.util.CollisionUtil.COLLISION_FLAG_ADD_TICKET; + } + + return flags; + } + // Sakura end public boolean isLegacyTrackingEntity = false; @@ -1494,7 +1507,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S io.papermc.paper.util.CollisionUtil.getCollisions( world, this, collisionBox, potentialCollisionsVoxel, potentialCollisionsBB, - io.papermc.paper.util.CollisionUtil.COLLISION_FLAG_CHECK_BORDER, + io.papermc.paper.util.CollisionUtil.COLLISION_FLAG_CHECK_BORDER | this.getExtraCollisionFlags(), // Sakura null, null ); @@ -4875,7 +4888,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S @Override public boolean isAlwaysTicking() { - return false; + return this.loadChunks; // Sakura - always tick in chunks } public boolean mayInteract(Level world, BlockPos pos) { diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java index ec8488a2ab16950052a3bff04be6e3ecc3b44891..1a018e1d2b6dd93be5e6209a2d52eade0b356f58 100644 --- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java @@ -74,6 +74,7 @@ public class FallingBlockEntity extends Entity { this.dropItem = true; this.fallDamageMax = 40; this.isFallingBlock = true; // Sakura + this.loadChunks = world.sakuraConfig().cannons.sand.loadsChunks; // Sakura - load chunks } public FallingBlockEntity(Level world, double x, double y, double z, BlockState block) { diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java index c187a2714d5580a2d8db54d270999aa618c4c878..0be7c39fbb19a0cdca3f5dc779c2690df5f08647 100644 --- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java @@ -39,6 +39,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { super(type, world); this.blocksBuilding = true; this.isPrimedTNT = true; // Sakura + this.loadChunks = world.sakuraConfig().cannons.tnt.loadsChunks; // Sakura - load chunks } public PrimedTnt(Level world, double x, double y, double z, @Nullable LivingEntity igniter) { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java index fa170cc1ce7011d201295b89718292d696c7fc24..2f48ac198610ee2a379bff4e056a6afe5f7f8a04 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -218,6 +218,17 @@ public class LevelChunk extends ChunkAccess { } } // Paper end + // Sakura start + private long lastMovementLoadTicket = 0; + + public boolean movementLoadTicketRequiresUpdate() { + return net.minecraft.server.MinecraftServer.currentTickLong - this.lastMovementLoadTicket >= 100; + } + + public void updatedMovementLoadTicket() { + this.lastMovementLoadTicket = net.minecraft.server.MinecraftServer.currentTickLong; + } + // Sakura end public LevelChunk(ServerLevel world, ProtoChunk protoChunk, @Nullable LevelChunk.PostLoadProcessor entityLoader) { this(world, protoChunk.getPos(), protoChunk.getUpgradeData(), protoChunk.unpackBlockTicks(), protoChunk.unpackFluidTicks(), protoChunk.getInhabitedTime(), protoChunk.getSections(), entityLoader, protoChunk.getBlendingData());