mirror of
https://github.com/YatopiaMC/Yatopia.git
synced 2024-12-01 15:13:24 +01:00
ab975588e5
Also dropped a patch that I think was kinda unnecessary.
324 lines
16 KiB
Diff
324 lines
16 KiB
Diff
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 63a761ebef80d4af09cdc2682e496d78492c4a3a..d97373816e9c44edc2de090bd22aa696404e0012 100644
|
|
--- a/src/main/java/net/minecraft/server/BehaviorFindPosition.java
|
|
+++ b/src/main/java/net/minecraft/server/BehaviorFindPosition.java
|
|
@@ -16,7 +16,7 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
|
|
private final VillagePlaceType b;
|
|
private final MemoryModuleType<GlobalPos> c;
|
|
private final boolean d;
|
|
- private final Optional<Byte> e;
|
|
+ private final Optional<Byte> e; private Optional<Byte> getPoiAquisitionEvent() { return this.e; } // Yatopia - OBFHELPER
|
|
private long f;
|
|
private final Long2ObjectMap<BehaviorFindPosition.a> g;
|
|
|
|
@@ -48,7 +48,7 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
|
|
if (this.d && entitycreature.isBaby()) {
|
|
return false;
|
|
} else if (this.f == 0L) {
|
|
- this.f = entitycreature.world.getTime() + (long) worldserver.random.nextInt(20);
|
|
+ this.f = entitycreature.world.getTime() + (long) java.util.concurrent.ThreadLocalRandom.current().nextInt(20); // Yatopia
|
|
return false;
|
|
} else {
|
|
return worldserver.getTime() >= this.f;
|
|
@@ -56,12 +56,57 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
|
|
}
|
|
|
|
protected void a(WorldServer worldserver, EntityCreature entitycreature, long i) {
|
|
- this.f = i + 20L + (long) worldserver.getRandom().nextInt(20);
|
|
+ this.f = i + 20L + (long) java.util.concurrent.ThreadLocalRandom.current().nextInt(20); // Yatopia
|
|
VillagePlace villageplace = worldserver.y();
|
|
|
|
+ // 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.hasVacancy()) continue;
|
|
+
|
|
+ BlockPosition pos = record.getPosition();
|
|
+ long key = pos.asLong();
|
|
+ if (this.g.containsKey(key)) {
|
|
+ continue;
|
|
+ }
|
|
+ double poiDist = pos.distanceSquared(blockposition2);
|
|
+ if (poiDist <= (double) requiredDist) {
|
|
+ this.g.put(key, new BehaviorFindPosition.a(java.util.concurrent.ThreadLocalRandom.current(), (long) (this.f + 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()) {
|
|
+ GlobalPos globalPos = GlobalPos.create(worldserver.getDimensionKey(), pos);
|
|
+ entitycreature.getBehaviorController().setMemory(c, globalPos);
|
|
+ this.getPoiAquisitionEvent().ifPresent((event) -> worldserver.broadcastEntityEffect(entitycreature, event));
|
|
+ break OUT;
|
|
+ }
|
|
+ if (poiAttempts >= maxPoiAttempts) {
|
|
+ break OUT;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
this.g.long2ObjectEntrySet().removeIf((entry) -> {
|
|
- return !((BehaviorFindPosition.a) entry.getValue()).b(i);
|
|
+ return entry.getValue().b < f;
|
|
});
|
|
+ /*
|
|
Predicate<BlockPosition> predicate = (blockposition) -> {
|
|
BehaviorFindPosition.a behaviorfindposition_a = (BehaviorFindPosition.a) this.g.get(blockposition.asLong());
|
|
|
|
@@ -102,7 +147,7 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
|
|
});
|
|
}
|
|
}
|
|
-
|
|
+ */ // Yatopia end
|
|
}
|
|
|
|
static class a {
|
|
diff --git a/src/main/java/net/minecraft/server/PathEntity.java b/src/main/java/net/minecraft/server/PathEntity.java
|
|
index c81a5d50c480b064ab60ed6f25f9e2c0bedb6ece..a86ad4c8a28b9aacdb1e99320fddf2344b08bd7e 100644
|
|
--- a/src/main/java/net/minecraft/server/PathEntity.java
|
|
+++ b/src/main/java/net/minecraft/server/PathEntity.java
|
|
@@ -114,6 +114,7 @@ public class PathEntity {
|
|
}
|
|
}
|
|
|
|
+ public final boolean canReach() { return j(); } // Yatopia - OBFHELPER
|
|
public boolean j() {
|
|
return this.h;
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/RegionFileSection.java b/src/main/java/net/minecraft/server/RegionFileSection.java
|
|
index 04256a95108b8182e8f808e856e0d2b62165e242..69cc2d1a0642029793827f4195723c380e01c821 100644
|
|
--- a/src/main/java/net/minecraft/server/RegionFileSection.java
|
|
+++ b/src/main/java/net/minecraft/server/RegionFileSection.java
|
|
@@ -52,10 +52,13 @@ 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 - replace method - never load POI data sync, we load this in chunk load already, reduce ops
|
|
+ /*
|
|
SectionPosition sectionposition = SectionPosition.a(i);
|
|
|
|
if (this.b(sectionposition)) {
|
|
@@ -75,6 +78,10 @@ public class RegionFileSection<R> extends RegionFileCache implements AutoCloseab
|
|
}
|
|
}
|
|
}
|
|
+ */
|
|
+ // If it's an unloaded chunk, well too bad.
|
|
+ return this.c(i);
|
|
+ // Yatopia end
|
|
}
|
|
|
|
protected boolean b(SectionPosition sectionposition) {
|
|
@@ -118,7 +125,7 @@ public class RegionFileSection<R> extends RegionFileCache implements AutoCloseab
|
|
private <T> void a(ChunkCoordIntPair chunkcoordintpair, DynamicOps<T> dynamicops, @Nullable T t0) {
|
|
if (t0 == null) {
|
|
for (int i = 0; i < 16; ++i) {
|
|
- this.c.put(SectionPosition.a(chunkcoordintpair, i).s(), Optional.empty());
|
|
+ //this.c.put(SectionPosition.a(chunkcoordintpair, i).s(), Optional.empty()); // Yatopia - NO!!!
|
|
}
|
|
} else {
|
|
Dynamic<T> dynamic = new Dynamic(dynamicops, t0);
|
|
@@ -140,7 +147,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
|
|
optional.ifPresent((object) -> {
|
|
this.b(i1);
|
|
if (flag) {
|
|
@@ -213,7 +220,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 f95925f1c5d091f1a129d0437bb6e175c6ac080f..cf5b25d9375724ea2afcf5cd59e0ccd302cdf45e 100644
|
|
--- a/src/main/java/net/minecraft/server/SectionPosition.java
|
|
+++ b/src/main/java/net/minecraft/server/SectionPosition.java
|
|
@@ -173,6 +173,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 0b40c2f4dada7d8432e3f91e9cf206c2bda3b24b..1b956d973ebef2345755201dec3449545c458a60 100644
|
|
--- a/src/main/java/net/minecraft/server/VillagePlaceRecord.java
|
|
+++ b/src/main/java/net/minecraft/server/VillagePlaceRecord.java
|
|
@@ -44,6 +44,7 @@ public class VillagePlaceRecord {
|
|
}
|
|
}
|
|
|
|
+ protected final boolean increaseVacancy() { return c(); } // Yatopia - OBFHELPER
|
|
protected boolean c() {
|
|
if (this.c >= this.b.b()) {
|
|
return false;
|
|
@@ -54,14 +55,17 @@ public class VillagePlaceRecord {
|
|
}
|
|
}
|
|
|
|
+ public final boolean hasVacancy() { 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 77c66bc9952542d2444b402896a3d9f622ca2ff9..d4018b9b615dae2b9e30517be51322656601b171 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 a5718af9b614ae505067131f04ebb490617d6aa4..142b47df08991a3e72c9f7927af6933a72f7b4cb 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.g().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)));
|
|
}
|
|
}
|