diff --git a/PATCHES.md b/PATCHES.md index 604332a7..893b040d 100644 --- a/PATCHES.md +++ b/PATCHES.md @@ -59,6 +59,7 @@ # Patches | server | Optimize BehaviorController | MrIvanPlays | | | server | Optimize Hopper logic | tr7zw | | | server | Optimize TileEntity loading | tr7zw | | +| server | Optimize Villagers | Aikar | MrIvanPlays | | server | Optimize inventory API item handling | Phoenix616 | | | server | Optimize player loops around weather | MrIvanPlays | | | server | Optimize redstone algorithm | theosib | egg82 | diff --git a/patches/server/0033-Optimize-Villagers.patch b/patches/server/0033-Optimize-Villagers.patch new file mode 100644 index 00000000..f1cfcff7 --- /dev/null +++ b/patches/server/0033-Optimize-Villagers.patch @@ -0,0 +1,323 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 10 Aug 2020 17:12:02 +0300 +Subject: [PATCH] Optimize Villagers + +This change reimplements the entire BehaviorFindPosition method to +get rid of all of the streams, and implement the logic in a more sane way. + +We keep vanilla behavior 100% the same with this change, just wrote more +optimal, as we can abort iterating POI's as soon as we find a match... + +One slight change is that Minecraft adds a random delay before a POI is +attempted again. I've increased the amount of that delay based on the distance +to said POI, so farther POI's will not be attempted as often. + +Additionally, we spiral out, so we favor local POI's before we ever favor farther POI's. + +We also try to pathfind 1 POI at a time instead of collecting multiple POI's then tossing them +all to the pathfinder, so that once we get a match we can return before even looking at other +POI's. + +This benefits us in that ideally, a villager will constantly find the near POI's and +not even try to pathfind to the farther POI. Trying to pathfind to distant POI's is +what causes significant lag. + +Other improvements here is to stop spamming the POI manager with empty nullables. +Vanilla used them to represent if they needed to load POI data off disk or not. + +Well, we load POI data async on chunk load, so we have it, and we surely do not ever +want to load POI data sync either for unloaded chunks! + +So this massively reduces object count in the POI hashmaps, resulting in less hash collions, +and also less memory use. + +Additionally, unemployed villagers were using significant time due to major inefficiency in +the code rebuilding data that is static every single invocation of every POI type... + +So we cache that and only rebuild it if professions change, which should be never unless +a plugin manipulates and adds custom professions, which it will handle by rebuilding. + +Ported to Yatopia and 1.16.1 by MrIvanPlays +Co-authored-by: MrIvanPlays + +diff --git a/src/main/java/net/minecraft/server/BehaviorFindPosition.java b/src/main/java/net/minecraft/server/BehaviorFindPosition.java +index 84a872dfd35249972129130083d51d71d75bff1e..15ea264e49609de61be131d41ae68e65957d002b 100644 +--- a/src/main/java/net/minecraft/server/BehaviorFindPosition.java ++++ b/src/main/java/net/minecraft/server/BehaviorFindPosition.java +@@ -45,7 +45,7 @@ public class BehaviorFindPosition extends Behavior { + if (this.d && entitycreature.isBaby()) { + return false; + } else if (this.e == 0L) { +- this.e = entitycreature.world.getTime() + (long) worldserver.random.nextInt(20); ++ this.e = entitycreature.world.getTime() + (long) java.util.concurrent.ThreadLocalRandom.current().nextInt(20); // Yatopia + return false; + } else { + return worldserver.getTime() >= this.e; +@@ -53,12 +53,57 @@ public class BehaviorFindPosition extends Behavior { + } + + protected void a(WorldServer worldserver, EntityCreature entitycreature, long i) { +- this.e = i + 20L + (long) worldserver.getRandom().nextInt(20); ++ this.e = i + 20L + (long) java.util.concurrent.ThreadLocalRandom.current().nextInt(20); // Yatopia + VillagePlace villageplace = worldserver.x(); + ++ // Yatopia start - replace implementation completely ++ BlockPosition blockposition2 = new BlockPosition(entitycreature.locX(), entitycreature.locY(), entitycreature.locZ()); ++ int dist = 48; ++ int requiredDist = dist * dist; ++ int cdist = Math.floorDiv(dist, 16); ++ Predicate predicate = this.b.getPredicate(); ++ int maxPoiAttempts = 4; ++ int poiAttempts = 0; ++ OUT: ++ for (ChunkCoordIntPair chunkcoordintpair : MCUtil.getSpiralOutChunks(blockposition2, cdist)) { ++ for (int i1 = 0; i1 < 16; i1++) { ++ java.util.Optional section = villageplace.getSection(SectionPosition.a(chunkcoordintpair, i1).asLong()); ++ if (section == null || !section.isPresent()) continue; ++ for (java.util.Map.Entry> e : section.get().getRecords().entrySet()) { ++ if (!predicate.test(e.getKey())) continue; ++ for (VillagePlaceRecord record : e.getValue()) { ++ if (!record.hasVacany()) continue; ++ ++ BlockPosition pos = record.getPosition(); ++ long key = pos.asLong(); ++ if (this.f.containsKey(key)) { ++ continue; ++ } ++ double poiDist = pos.distanceSquared(blockposition2); ++ if (poiDist <= (double) requiredDist) { ++ this.f.put(key, new BehaviorFindPosition.a(java.util.concurrent.ThreadLocalRandom.current(), (long) (this.e + Math.sqrt(poiDist) * 4))); // use dist instead of 40 to blacklist longer if farther distance ++ ++poiAttempts; ++ PathEntity pathentity = entitycreature.getNavigation().a(com.google.common.collect.ImmutableSet.of(pos), 8, false, this.b.getValidRange()); ++ ++ if (pathentity != null && pathentity.canReach()) { ++ record.decreaseVacany(); ++ GlobalPos globalPos = GlobalPos.create(worldserver.getDimensionKey(), pos); ++ entitycreature.getBehaviorController().setMemory(c, globalPos); ++ break OUT; ++ } ++ if (poiAttempts >= maxPoiAttempts) { ++ break OUT; ++ } ++ } ++ } ++ } ++ } ++ } ++ + this.f.long2ObjectEntrySet().removeIf((entry) -> { +- return !((BehaviorFindPosition.a) entry.getValue()).b(i); ++ return entry.getValue().b < e; + }); ++ /* + Predicate predicate = (blockposition) -> { + BehaviorFindPosition.a behaviorfindposition_a = (BehaviorFindPosition.a) this.f.get(blockposition.asLong()); + +@@ -96,6 +141,7 @@ public class BehaviorFindPosition extends Behavior { + }); + } + } ++ */ // Yatopia end + + } + +diff --git a/src/main/java/net/minecraft/server/PathEntity.java b/src/main/java/net/minecraft/server/PathEntity.java +index 9154c01a22bc7b6d2dd390bb7b6e21ef52c8006c..e86e09be4990bc6b7a36ab1ad74dba7022f49428 100644 +--- a/src/main/java/net/minecraft/server/PathEntity.java ++++ b/src/main/java/net/minecraft/server/PathEntity.java +@@ -106,6 +106,7 @@ public class PathEntity { + } + } + ++ public final boolean canReach() { return i(); } // Yatopia - OBFHELPER + public boolean i() { + return this.h; + } +diff --git a/src/main/java/net/minecraft/server/RegionFileSection.java b/src/main/java/net/minecraft/server/RegionFileSection.java +index bd0ff1e43a07a3332f9ade49fec2f76275a25c7f..f99be13169cfbca05cc440e7abef2197036b3d7d 100644 +--- a/src/main/java/net/minecraft/server/RegionFileSection.java ++++ b/src/main/java/net/minecraft/server/RegionFileSection.java +@@ -52,10 +52,12 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab + + @Nullable + protected Optional c(long i) { +- return (Optional) this.c.get(i); ++ return this.c.getOrDefault(i, Optional.empty()); // Yatopia + } + ++ protected final Optional getSection(long i) { return d(i); } // Yatopia - OBFHELPER + protected Optional d(long i) { ++ /* // Yatopia start - replaced logic + SectionPosition sectionposition = SectionPosition.a(i); + + if (this.b(sectionposition)) { +@@ -75,6 +77,10 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab + } + } + } ++ */ ++ // Never load POI data sync, we load this in chunk load already, reduce ops ++ // If it's an unloaded chunk, well too bad. ++ return c(i); + } + + protected boolean b(SectionPosition sectionposition) { +@@ -117,9 +123,11 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab + + private void a(ChunkCoordIntPair chunkcoordintpair, DynamicOps dynamicops, @Nullable T t0) { + if (t0 == null) { ++ /* // Yatopia start - NO!!! + for (int i = 0; i < 16; ++i) { + this.c.put(SectionPosition.a(chunkcoordintpair, i).s(), Optional.empty()); + } ++ */ // Yatopia end + } else { + Dynamic dynamic = new Dynamic(dynamicops, t0); + int j = a(dynamic); +@@ -140,7 +148,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab + return dataresult.resultOrPartial(logger::error); + }); + +- this.c.put(i1, optional); ++ if (optional.isPresent()) this.c.put(i1, optional); // Yatopia - NO!!! + optional.ifPresent((object) -> { + this.b(i1); + if (flag) { +@@ -213,7 +221,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab + if (optional != null && optional.isPresent()) { + this.d.add(i); + } else { +- RegionFileSection.LOGGER.warn("No data for position: {}", SectionPosition.a(i)); ++ //RegionFileSection.LOGGER.warn("No data for position: {}", SectionPosition.a(i)); // Yatopia - hush + } + } + +diff --git a/src/main/java/net/minecraft/server/SectionPosition.java b/src/main/java/net/minecraft/server/SectionPosition.java +index 7806f3c351cba3f0388da11888f900c48004dadf..6556533acb04f57284f7493c7683232e9dddbd48 100644 +--- a/src/main/java/net/minecraft/server/SectionPosition.java ++++ b/src/main/java/net/minecraft/server/SectionPosition.java +@@ -145,6 +145,7 @@ public class SectionPosition extends BaseBlockPosition { + return (((long) i & 4194303L) << 42) | (((long) j & 1048575L)) | (((long) k & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } + ++ public long asLong() { return s(); } // Yatopia - OBFHELPER + public long s() { + return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } +diff --git a/src/main/java/net/minecraft/server/VillagePlaceRecord.java b/src/main/java/net/minecraft/server/VillagePlaceRecord.java +index e5d2304808b2bb93041523968f0b88e020c61c1e..2647dc3646e332189a88d17e08831882e40f2910 100644 +--- a/src/main/java/net/minecraft/server/VillagePlaceRecord.java ++++ b/src/main/java/net/minecraft/server/VillagePlaceRecord.java +@@ -34,6 +34,7 @@ public class VillagePlaceRecord { + this(blockposition, villageplacetype, villageplacetype.b(), runnable); + } + ++ public final boolean decreaseVacany() { return b(); } // Yatopia - OBFHELPER + protected boolean b() { + if (this.c <= 0) { + return false; +@@ -44,6 +45,7 @@ public class VillagePlaceRecord { + } + } + ++ public final boolean increaseVacany() { return c(); } // Yatopia - OBFHELPER + protected boolean c() { + if (this.c >= this.b.b()) { + return false; +@@ -54,14 +56,17 @@ public class VillagePlaceRecord { + } + } + ++ public final boolean hasVacany() { return d(); } // Yatopia - OBFHELPER + public boolean d() { + return this.c > 0; + } + ++ public final boolean isOccupied() { return e(); } // Yatopia - OBFHELPER + public boolean e() { + return this.c != this.b.b(); + } + ++ public final BlockPosition getPosition() { return f(); } // Yatopia - OBFHELPER + public BlockPosition f() { + return this.a; + } +diff --git a/src/main/java/net/minecraft/server/VillagePlaceSection.java b/src/main/java/net/minecraft/server/VillagePlaceSection.java +index e82dcdbce698e2e9bc449fa639b7219821844e14..3aaba7fcaf83a491b9da60d156b7f2379f5a6aeb 100644 +--- a/src/main/java/net/minecraft/server/VillagePlaceSection.java ++++ b/src/main/java/net/minecraft/server/VillagePlaceSection.java +@@ -23,12 +23,12 @@ public class VillagePlaceSection { + + private static final Logger LOGGER = LogManager.getLogger(); + private final Short2ObjectMap b; +- private final Map> c; ++ private final Map> c; public final Map> getRecords() { return c; } // Yatopia - OBFHELPER + private final Runnable d; + private boolean e; + + public static Codec a(Runnable runnable) { +- Codec codec = RecordCodecBuilder.create((instance) -> { ++ Codec codec = RecordCodecBuilder.create((instance) -> { // Yatopia - decompile fix + return instance.group(RecordCodecBuilder.point(runnable), Codec.BOOL.optionalFieldOf("Valid", false).forGetter((villageplacesection) -> { + return villageplacesection.e; + }), VillagePlaceRecord.a(runnable).listOf().fieldOf("Records").forGetter((villageplacesection) -> { +diff --git a/src/main/java/net/minecraft/server/VillagePlaceType.java b/src/main/java/net/minecraft/server/VillagePlaceType.java +index 5bd3bcc2b96f7da21d363809a547b0567407ee75..1fb87bf395ced15bc3ef383dae46a42c5e4d2547 100644 +--- a/src/main/java/net/minecraft/server/VillagePlaceType.java ++++ b/src/main/java/net/minecraft/server/VillagePlaceType.java +@@ -14,11 +14,20 @@ import java.util.stream.Collectors; + + public class VillagePlaceType { + ++ static Set professionCache; // Yatopia + private static final Supplier> y = Suppliers.memoize(() -> { + return (Set) IRegistry.VILLAGER_PROFESSION.e().map(VillagerProfession::b).collect(Collectors.toSet()); + }); + public static final Predicate a = (villageplacetype) -> { +- return ((Set) VillagePlaceType.y.get()).contains(villageplacetype); ++ // Yatopia start ++ if (professionCache == null) { ++ professionCache = new java.util.HashSet<>(); ++ for (VillagerProfession profession : IRegistry.VILLAGER_PROFESSION) { ++ professionCache.add(profession.getPlaceType()); ++ } ++ } ++ return professionCache.contains(villageplacetype); ++ // Yatopia end + }; + public static final Predicate b = (villageplacetype) -> { + return true; +@@ -83,10 +92,12 @@ public class VillagePlaceType { + return this.D; + } + ++ public final Predicate getPredicate() { return c(); } // Yatopia - OBFHELPER + public Predicate c() { + return this.E; + } + ++ public final int getValidRange() { return d(); } // Yatopia - OBFHELPER + public int d() { + return this.F; + } +diff --git a/src/main/java/net/minecraft/server/VillagerProfession.java b/src/main/java/net/minecraft/server/VillagerProfession.java +index 3c60da7ac6faebe9d964e893974e42613c59b4c1..1b012914cb3fcbc4bb456195ade96668b6742cfd 100644 +--- a/src/main/java/net/minecraft/server/VillagerProfession.java ++++ b/src/main/java/net/minecraft/server/VillagerProfession.java +@@ -35,6 +35,7 @@ public class VillagerProfession { + this.t = soundeffect; + } + ++ public final VillagePlaceType getPlaceType() { return b(); } // Yatopia - OBFHELPER + public VillagePlaceType b() { + return this.q; + } +@@ -61,6 +62,7 @@ public class VillagerProfession { + } + + static VillagerProfession a(String s, VillagePlaceType villageplacetype, ImmutableSet immutableset, ImmutableSet immutableset1, @Nullable SoundEffect soundeffect) { ++ VillagePlaceType.professionCache = null; // Yatopia + return (VillagerProfession) IRegistry.a((IRegistry) IRegistry.VILLAGER_PROFESSION, new MinecraftKey(s), (Object) (new VillagerProfession(s, villageplacetype, immutableset, immutableset1, soundeffect))); + } + } diff --git a/patches/server/0033-Intellij-Optimize-Imports.patch b/patches/server/0034-Intellij-Optimize-Imports.patch similarity index 99% rename from patches/server/0033-Intellij-Optimize-Imports.patch rename to patches/server/0034-Intellij-Optimize-Imports.patch index d4574297..e7c6a8cc 100644 --- a/patches/server/0033-Intellij-Optimize-Imports.patch +++ b/patches/server/0034-Intellij-Optimize-Imports.patch @@ -7563,7 +7563,7 @@ index 2369afb4f37863c5c59456e46c48ad0d32f9eeb7..d18359567b46e4bbd807ad8eeadb8bfe public interface PairedQueue { diff --git a/src/main/java/net/minecraft/server/PathEntity.java b/src/main/java/net/minecraft/server/PathEntity.java -index 9154c01a22bc7b6d2dd390bb7b6e21ef52c8006c..d786c3d2eb4e06e20b5125b7ef8fa7d929eb4d01 100644 +index e86e09be4990bc6b7a36ab1ad74dba7022f49428..1660f6a0eeb061ce426b89e2d11f05c882abe582 100644 --- a/src/main/java/net/minecraft/server/PathEntity.java +++ b/src/main/java/net/minecraft/server/PathEntity.java @@ -1,7 +1,7 @@ @@ -8484,7 +8484,7 @@ index 29137f495942d810e61fadc33178999ad57fdcc0..a4c1eb60ab7349cb3146018642cc753f public class RegionFileCompression { diff --git a/src/main/java/net/minecraft/server/RegionFileSection.java b/src/main/java/net/minecraft/server/RegionFileSection.java -index bd0ff1e43a07a3332f9ade49fec2f76275a25c7f..41e1f7c8e22fadc7fe45e03f480f5ee9fef192b2 100644 +index f99be13169cfbca05cc440e7abef2197036b3d7d..ea2897eadb4c8bdd7fdc6ae55a51a77d545fc847 100644 --- a/src/main/java/net/minecraft/server/RegionFileSection.java +++ b/src/main/java/net/minecraft/server/RegionFileSection.java @@ -3,23 +3,20 @@ package net.minecraft.server; @@ -16125,30 +16125,30 @@ index d3281c81a4e8e0b8c2ad3a8d6628faf546746a2f..bb3400d2ccce6fb73550f80ef1df5a48 * If you are getting: java.lang.ExceptionInInitializerError * at net.minecraft.server.StatisticList.<clinit>(SourceFile:58) diff --git a/src/test/java/org/bukkit/support/DummyServer.java b/src/test/java/org/bukkit/support/DummyServer.java -index 97eb5fa880d009bef973467403323d022bea5d7a..1036bd4e8fcf5e7ae65388cdc54b770c125e2547 100644 +index 97eb5fa880d009bef973467403323d022bea5d7a..39411685ed566b738a40a050fad2159c72bca264 100644 --- a/src/test/java/org/bukkit/support/DummyServer.java +++ b/src/test/java/org/bukkit/support/DummyServer.java @@ -1,10 +1,5 @@ - package org.bukkit.support; - --import java.lang.reflect.InvocationHandler; --import java.lang.reflect.Method; --import java.lang.reflect.Proxy; --import java.util.HashMap; --import java.util.logging.Logger; - import org.bukkit.Bukkit; - import org.bukkit.Material; - import org.bukkit.NamespacedKey; + package org.bukkit.support; + +-import java.lang.reflect.InvocationHandler; +-import java.lang.reflect.Method; +-import java.lang.reflect.Proxy; +-import java.util.HashMap; +-import java.util.logging.Logger; + import org.bukkit.Bukkit; + import org.bukkit.Material; + import org.bukkit.NamespacedKey; @@ -16,6 +11,12 @@ import org.bukkit.craftbukkit.util.CraftMagicNumbers; - import org.bukkit.craftbukkit.util.CraftNamespacedKey; - import org.bukkit.craftbukkit.util.Versioning; - + import org.bukkit.craftbukkit.util.CraftNamespacedKey; + import org.bukkit.craftbukkit.util.Versioning; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.logging.Logger; + - public final class DummyServer implements InvocationHandler { - private static interface MethodHandler { - Object handle(DummyServer server, Object[] args); + public final class DummyServer implements InvocationHandler { + private static interface MethodHandler { + Object handle(DummyServer server, Object[] args); diff --git a/patches/server/0034-Intellij-Code-Clean-Up.patch b/patches/server/0035-Intellij-Code-Clean-Up.patch similarity index 99% rename from patches/server/0034-Intellij-Code-Clean-Up.patch rename to patches/server/0035-Intellij-Code-Clean-Up.patch index 2d9304ef..6ad5d3e5 100644 --- a/patches/server/0034-Intellij-Code-Clean-Up.patch +++ b/patches/server/0035-Intellij-Code-Clean-Up.patch @@ -24993,7 +24993,7 @@ index d18359567b46e4bbd807ad8eeadb8bfeff533bf8..951c3f0368024d79d5856040e563b2b2 } diff --git a/src/main/java/net/minecraft/server/PathEntity.java b/src/main/java/net/minecraft/server/PathEntity.java -index d786c3d2eb4e06e20b5125b7ef8fa7d929eb4d01..63b02823bf0dcc79a0cd565b5bccdcd053ff1016 100644 +index 1660f6a0eeb061ce426b89e2d11f05c882abe582..059543cd32ed205d2720372f86855a22556e30b0 100644 --- a/src/main/java/net/minecraft/server/PathEntity.java +++ b/src/main/java/net/minecraft/server/PathEntity.java @@ -17,7 +17,7 @@ public class PathEntity { @@ -27861,19 +27861,10 @@ index a4c1eb60ab7349cb3146018642cc753f403b61d9..7aaea270a9414f79ab3f880a3aadc15c @FunctionalInterface diff --git a/src/main/java/net/minecraft/server/RegionFileSection.java b/src/main/java/net/minecraft/server/RegionFileSection.java -index 41e1f7c8e22fadc7fe45e03f480f5ee9fef192b2..046ff8ec7f04089d913b561afb68e93120161b5a 100644 +index ea2897eadb4c8bdd7fdc6ae55a51a77d545fc847..4795e549b7b2740361c8cef088191ebca090a05b 100644 --- a/src/main/java/net/minecraft/server/RegionFileSection.java +++ b/src/main/java/net/minecraft/server/RegionFileSection.java -@@ -49,7 +49,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab - - @Nullable - protected Optional c(long i) { -- return (Optional) this.c.get(i); -+ return this.c.get(i); - } - - protected Optional d(long i) { -@@ -66,7 +66,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab +@@ -68,7 +68,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab this.b(sectionposition.r()); optional = this.c(i); if (optional == null) { @@ -27882,7 +27873,7 @@ index 41e1f7c8e22fadc7fe45e03f480f5ee9fef192b2..046ff8ec7f04089d913b561afb68e931 } else { return optional; } -@@ -152,7 +152,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab +@@ -160,7 +160,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab private void d(ChunkCoordIntPair chunkcoordintpair) { Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); // Paper - conflict here to avoid adding obfhelpers :) @@ -27891,7 +27882,7 @@ index 41e1f7c8e22fadc7fe45e03f480f5ee9fef192b2..046ff8ec7f04089d913b561afb68e931 if (nbtbase instanceof NBTTagCompound) { try { this.write(chunkcoordintpair, (NBTTagCompound) nbtbase); } catch (IOException ioexception) { RegionFileSection.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker // TODO make this write async -@@ -165,7 +165,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab +@@ -173,7 +173,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab // Paper start - internal get data function, copied from above private NBTTagCompound getDataInternal(ChunkCoordIntPair chunkcoordintpair) { Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); @@ -27900,7 +27891,7 @@ index 41e1f7c8e22fadc7fe45e03f480f5ee9fef192b2..046ff8ec7f04089d913b561afb68e931 if (nbtbase instanceof NBTTagCompound) { return (NBTTagCompound)nbtbase; -@@ -183,7 +183,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab +@@ -191,7 +191,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab long j = SectionPosition.a(chunkcoordintpair, i).s(); this.d.remove(j); @@ -27909,7 +27900,7 @@ index 41e1f7c8e22fadc7fe45e03f480f5ee9fef192b2..046ff8ec7f04089d913b561afb68e931 if (optional != null && optional.isPresent()) { DataResult dataresult = ((Codec) this.e.apply(() -> { -@@ -205,7 +205,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab +@@ -213,7 +213,7 @@ public class RegionFileSection extends RegionFileCache implements AutoCloseab protected void b(long i) {} protected void a(long i) { @@ -28167,10 +28158,10 @@ index cf15f7038ab4c392623b39ef676d3a24227f6e51..3bbabe64acff9ea947e76e8e57303067 entityplayer.playerConnection.sendPacket(packet); } diff --git a/src/main/java/net/minecraft/server/SectionPosition.java b/src/main/java/net/minecraft/server/SectionPosition.java -index 7806f3c351cba3f0388da11888f900c48004dadf..bba26f988c34c675ca6d570033848816546967bb 100644 +index 6556533acb04f57284f7493c7683232e9dddbd48..f09ff3b08d9e10bd7f4c0938e876fd08c3ec8a39 100644 --- a/src/main/java/net/minecraft/server/SectionPosition.java +++ b/src/main/java/net/minecraft/server/SectionPosition.java -@@ -162,7 +162,7 @@ public class SectionPosition extends BaseBlockPosition { +@@ -163,7 +163,7 @@ public class SectionPosition extends BaseBlockPosition { } public static Stream a(final int i, final int j, final int k, final int l, final int i1, final int j1) {