From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Ivan Pekov Date: Sat, 12 Sep 2020 19:17:05 +0300 Subject: [PATCH] Optimize Villagers These changes aim to fix the following: - Villagers trying to push farther POIs (Points Of Interest) - Villagers ignoring doors most of the times - Villagers pushing POIs (Points Of Interest) to unloaded chunks The following has been done to fix the mentioned problems: - Replaced stream off BehaviorFindPosition - Made sure that chunks are loaded for the POIs (Points Of Interest) that are gonna be tried. - Added a profession cache, which followed by a stream removal. - Added a config option, villagers-only-open-doors-if-attacked-by-mobs , the default of is "true", defaulting to vanilla behavior. If the specified option is false, then if the villager is not going to a path, he will try to go to the nearest door. diff --git a/src/main/java/de/minebench/origami/OrigamiConfig.java b/src/main/java/de/minebench/origami/OrigamiConfig.java index 9549b857020bb749c039420950684c74c1108945..d3fd3c41092dbd80f9ae774f57bca0716d71cd95 100644 --- a/src/main/java/de/minebench/origami/OrigamiConfig.java +++ b/src/main/java/de/minebench/origami/OrigamiConfig.java @@ -170,6 +170,11 @@ public final class OrigamiConfig { private void useBlockDistanceInPortalSearchRadius() { useBlockDistanceInPortalSearchRadius = getBoolean("use-block-distance-in-portal-search-radius", false); } + + public boolean villagersOnlyOpenDoorsIfAttackedByMobs = true; + private void villagersOnlyOpenDoorsIfAttackedByMobs() { + villagersOnlyOpenDoorsIfAttackedByMobs = getBoolean("villagers-only-open-doors-if-attacked-by-mobs", true); + } // Yatopia end } diff --git a/src/main/java/net/minecraft/server/BehaviorFindPosition.java b/src/main/java/net/minecraft/server/BehaviorFindPosition.java index 63a761ebef80d4af09cdc2682e496d78492c4a3a..047910f441b5e8ad97024177afbac703a0d0c5e9 100644 --- a/src/main/java/net/minecraft/server/BehaviorFindPosition.java +++ b/src/main/java/net/minecraft/server/BehaviorFindPosition.java @@ -48,7 +48,7 @@ public class BehaviorFindPosition extends Behavior { 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,7 +56,7 @@ public class BehaviorFindPosition extends Behavior { } 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(); this.g.long2ObjectEntrySet().removeIf((entry) -> { @@ -66,15 +66,32 @@ public class BehaviorFindPosition extends Behavior { BehaviorFindPosition.a behaviorfindposition_a = (BehaviorFindPosition.a) this.g.get(blockposition.asLong()); if (behaviorfindposition_a == null) { - return true; + return worldserver.getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; // Yatopia } else if (!behaviorfindposition_a.c(i)) { return false; } else { + // Yatopia start - make sure chunks are loaded + int chunkX = blockposition.getX() >> 4; + int chunkZ = blockposition.getZ() >> 4; + if (worldserver.getChunkIfLoaded(chunkX, chunkZ) != null) { behaviorfindposition_a.a(i); return true; + } else { + return false; + } + // Yatopia end } }; - Set set = (Set) villageplace.b(this.b.c(), predicate, entitycreature.getChunkCoordinates(), 48, VillagePlace.Occupancy.HAS_SPACE).limit(5L).collect(Collectors.toSet()); + // Yatopia start - replace stream + //Set set = (Set) villageplace.b(this.b.c(), predicate, entitycreature.getChunkCoordinates(), 48, VillagePlace.Occupancy.HAS_SPACE).limit(5L).collect(Collectors.toSet()); + Set set = new java.util.HashSet<>(); + int limit = 5; + for (BlockPosition pos : villageplace.bList(this.b.getCompletionCondition(), predicate, entitycreature.getChunkCoordinates(), 48, VillagePlace.Occupancy.HAS_SPACE)) { + set.add(pos); + limit--; + if (limit == 0) break; + } + // Yatopia end PathEntity pathentity = entitycreature.getNavigation().a(set, this.b.d()); if (pathentity != null && pathentity.j()) { @@ -84,7 +101,7 @@ public class BehaviorFindPosition extends Behavior { villageplace.a(this.b.c(), (blockposition1) -> { return blockposition1.equals(blockposition); }, blockposition, 1); - entitycreature.getBehaviorController().setMemory(this.c, (Object) GlobalPos.create(worldserver.getDimensionKey(), blockposition)); + entitycreature.getBehaviorController().setMemory(this.c, GlobalPos.create(worldserver.getDimensionKey(), blockposition)); // Yatopia - decompile fix this.e.ifPresent((obyte) -> { worldserver.broadcastEntityEffect(entitycreature, obyte); }); @@ -98,7 +115,7 @@ public class BehaviorFindPosition extends Behavior { BlockPosition blockposition1 = (BlockPosition) iterator.next(); this.g.computeIfAbsent(blockposition1.asLong(), (j) -> { - return new BehaviorFindPosition.a(entitycreature.world.random, i); + return new BehaviorFindPosition.a(java.util.concurrent.ThreadLocalRandom.current(), i); // Yatopia }); } } diff --git a/src/main/java/net/minecraft/server/BehaviorInteractDoor.java b/src/main/java/net/minecraft/server/BehaviorInteractDoor.java index 31f9001142ff8507499098f7da013b2b61d6847b..eb1df4046a81a011901d2763b51f2b5885e2095f 100644 --- a/src/main/java/net/minecraft/server/BehaviorInteractDoor.java +++ b/src/main/java/net/minecraft/server/BehaviorInteractDoor.java @@ -128,6 +128,12 @@ public class BehaviorInteractDoor extends Behavior { BehaviorController behaviorcontroller = entityliving.getBehaviorController(); // Yatopia start - replaced logic + if (!worldserver.origamiConfig.villagersOnlyOpenDoorsIfAttackedByMobs) { + if (b(worldserver, entityliving, blockposition)) { + return false; + } + return blockposition.distanceSquared(entityliving.getPositionVector(), 2.0D); + } else { if (!behaviorcontroller.hasMemory(MemoryModuleType.MOBS)) return false; for (EntityLiving entity : behaviorcontroller.getMemory(MemoryModuleType.MOBS).get()) { if (entity.getEntityType() == entityliving.getEntityType() @@ -137,6 +143,7 @@ public class BehaviorInteractDoor extends Behavior { } } return false; + } /* return !behaviorcontroller.hasMemory(MemoryModuleType.MOBS) ? false : (behaviorcontroller.getMemory(MemoryModuleType.MOBS).get()).stream().filter((entityliving1) -> { // CraftBukkit - decompile error return entityliving1.getEntityType() == entityliving.getEntityType(); diff --git a/src/main/java/net/minecraft/server/VillagePlaceType.java b/src/main/java/net/minecraft/server/VillagePlaceType.java index a5718af9b614ae505067131f04ebb490617d6aa4..2ea0cfad4b35264cd3b70b930dd28de58c77d0c0 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.g().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,6 +92,7 @@ public class VillagePlaceType { return this.D; } + public final Predicate getCompletionCondition() { return c(); } // Yatopia - OBFHELPER public Predicate c() { return this.E; } 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))); } }