Port aikar's villager optimizations from 1.15.2 (#73)

* Port aikar's villager optimizations from 1.15.2

* Add to PATCHES.md

* Oopsie, sometimes I don't look where im typing

* Attempt at fixing villagers can't get professions

* Why is this if(true), should've been if(false)

* Nuke stream
This commit is contained in:
Ivan Pekov 2020-08-10 19:02:40 +03:00 committed by GitHub
parent 84ff4f9991
commit 14f7e17e6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 352 additions and 37 deletions

View File

@ -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 |

View File

@ -0,0 +1,323 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
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 <ivan@mrivanplays.com>
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<EntityCreature> {
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<EntityCreature> {
}
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<VillagePlaceType> 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<VillagePlaceSection> section = villageplace.getSection(SectionPosition.a(chunkcoordintpair, i1).asLong());
+ if (section == null || !section.isPresent()) continue;
+ for (java.util.Map.Entry<VillagePlaceType, java.util.Set<VillagePlaceRecord>> 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<BlockPosition> predicate = (blockposition) -> {
BehaviorFindPosition.a behaviorfindposition_a = (BehaviorFindPosition.a) this.f.get(blockposition.asLong());
@@ -96,6 +141,7 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
});
}
}
+ */ // 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<R> extends RegionFileCache implements AutoCloseab
@Nullable
protected Optional<R> c(long i) {
- return (Optional) this.c.get(i);
+ return this.c.getOrDefault(i, Optional.empty()); // Yatopia
}
+ protected final Optional<R> getSection(long i) { return d(i); } // Yatopia - OBFHELPER
protected Optional<R> d(long i) {
+ /* // Yatopia start - replaced logic
SectionPosition sectionposition = SectionPosition.a(i);
if (this.b(sectionposition)) {
@@ -75,6 +77,10 @@ public class RegionFileSection<R> 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<R> extends RegionFileCache implements AutoCloseab
private <T> void a(ChunkCoordIntPair chunkcoordintpair, DynamicOps<T> 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<T> dynamic = new Dynamic(dynamicops, t0);
int j = a(dynamic);
@@ -140,7 +148,7 @@ public class RegionFileSection<R> 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<R> 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<VillagePlaceRecord> b;
- private final Map<VillagePlaceType, Set<VillagePlaceRecord>> c;
+ private final Map<VillagePlaceType, Set<VillagePlaceRecord>> c; public final Map<VillagePlaceType, Set<VillagePlaceRecord>> getRecords() { return c; } // Yatopia - OBFHELPER
private final Runnable d;
private boolean e;
public static Codec<VillagePlaceSection> a(Runnable runnable) {
- Codec codec = RecordCodecBuilder.create((instance) -> {
+ Codec<VillagePlaceSection> 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<VillagePlaceType> professionCache; // Yatopia
private static final Supplier<Set<VillagePlaceType>> y = Suppliers.memoize(() -> {
return (Set) IRegistry.VILLAGER_PROFESSION.e().map(VillagerProfession::b).collect(Collectors.toSet());
});
public static final Predicate<VillagePlaceType> 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<VillagePlaceType> b = (villageplacetype) -> {
return true;
@@ -83,10 +92,12 @@ public class VillagePlaceType {
return this.D;
}
+ public final Predicate<VillagePlaceType> getPredicate() { return c(); } // Yatopia - OBFHELPER
public Predicate<VillagePlaceType> 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<Item> immutableset, ImmutableSet<Block> 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)));
}
}

View File

@ -7563,7 +7563,7 @@ index 2369afb4f37863c5c59456e46c48ad0d32f9eeb7..d18359567b46e4bbd807ad8eeadb8bfe
public interface PairedQueue<T, F> {
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.&lt;clinit&gt;(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);

View File

@ -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<R> extends RegionFileCache implements AutoCloseab
@Nullable
protected Optional<R> c(long i) {
- return (Optional) this.c.get(i);
+ return this.c.get(i);
}
protected Optional<R> d(long i) {
@@ -66,7 +66,7 @@ public class RegionFileSection<R> extends RegionFileCache implements AutoCloseab
@@ -68,7 +68,7 @@ public class RegionFileSection<R> 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<R> extends RegionFileCache implements AutoCloseab
@@ -160,7 +160,7 @@ public class RegionFileSection<R> extends RegionFileCache implements AutoCloseab
private void d(ChunkCoordIntPair chunkcoordintpair) {
Dynamic<NBTBase> 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<R> extends RegionFileCache implements AutoCloseab
@@ -173,7 +173,7 @@ public class RegionFileSection<R> extends RegionFileCache implements AutoCloseab
// Paper start - internal get data function, copied from above
private NBTTagCompound getDataInternal(ChunkCoordIntPair chunkcoordintpair) {
Dynamic<NBTBase> 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<R> extends RegionFileCache implements AutoCloseab
@@ -191,7 +191,7 @@ public class RegionFileSection<R> 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<T> dataresult = ((Codec) this.e.apply(() -> {
@@ -205,7 +205,7 @@ public class RegionFileSection<R> extends RegionFileCache implements AutoCloseab
@@ -213,7 +213,7 @@ public class RegionFileSection<R> 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<SectionPosition> a(final int i, final int j, final int k, final int l, final int i1, final int j1) {