-
Bug
-
Resolution: Fixed
-
Minor
-
None
-
None
-
3482-Spigot-42b6152-e87f2e3 (MC: 1.18.2) (Implementing API version 1.18-R0.1-SNAPSHOT)
-
Yes
Any usage of of World#locateNearestStructure() returns null for a Stronghold.
java.lang.NullPointerException: Cannot invoke "org.bukkit.Location.getBlock()" because the return value of "org.bukkit.World.locateNearestStructure(org.bukkit.Location, org.bukkit.StructureType, int, boolean)" is null at net.andrewcpu.worldstar.WorldStarDriver.lambda$onChat$0(WorldStarDriver.java:58) ~[?:?] at org.bukkit.craftbukkit.v1_18_R2.scheduler.CraftTask.run(CraftTask.java:82) ~[spigot-1.18.2-R0.1-SNAPSHOT.jar:3482-Spigot-42b6152-e87f2e3] at org.bukkit.craftbukkit.v1_18_R2.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:415) ~[spigot-1.18.2-R0.1-SNAPSHOT.jar:3482-Spigot-42b6152-e87f2e3] at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1285) ~[spigot-1.18.2-R0.1-SNAPSHOT.jar:3482-Spigot-42b6152-e87f2e3] at net.minecraft.server.dedicated.DedicatedServer.b(DedicatedServer.java:429) ~[spigot-1.18.2-R0.1-SNAPSHOT.jar:3482-Spigot-42b6152-e87f2e3] at net.minecraft.server.MinecraftServer.a(MinecraftServer.java:1237) ~[spigot-1.18.2-R0.1-SNAPSHOT.jar:3482-Spigot-42b6152-e87f2e3] at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:1047) ~[spigot-1.18.2-R0.1-SNAPSHOT.jar:3482-Spigot-42b6152-e87f2e3] at net.minecraft.server.MinecraftServer.lambda$0(MinecraftServer.java:304) ~[spigot-1.18.2-R0.1-SNAPSHOT.jar:3482-Spigot-42b6152-e87f2e3] at java.lang.Thread.run(Thread.java:833) [?:?]
Symptoms:
- /locate stronghold works
- /locate #minecraft:eye_of_ender_located works
- World#locateNearestStructure() for a MINESHAFT works
- /locate mineshaft works
- World#locateNearestStructure() for STRONGHOLD does not work
- Tested locateNearestStructure() for STRONGHOLD with varying ranges, does not work
- Tested locateNearestStructure() for STRONGHOLD with both searching for unfound structures set to true and false, does not work
Investigation:
Existing findNearestMapFeature code in CB#WorldServer
@Nullable public BlockPosition findNearestMapFeature(TagKey<StructureFeature<?, ?>> tagkey, BlockPosition blockposition, int i, boolean flag) { if (!this.serverLevelData.worldGenSettings().generateFeatures()) { // CraftBukkit return null; } else { Optional<HolderSet.Named<StructureFeature<?, ?>>> optional = this.registryAccess().registryOrThrow(IRegistry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY).getTag(tagkey); if (optional.isEmpty()) { return null; } else { Pair<BlockPosition, Holder<StructureFeature<?, ?>>> pair = this.getChunkSource().getGenerator().findNearestMapFeature(this, (HolderSet) optional.get(), blockposition, i, flag); return pair != null ? (BlockPosition) pair.getFirst() : null; } } }
The Optional<HolderSet.Named> is coming back as empty for Strongholds and returning null without attempting to look for the proposed TagKey.
It seems that the IRegistry for the worlds does not have the ResourceKey added for Strongholds.
My proposed change: (Though may be unsafe, will need another set of eyes obviously)
@Nullable public BlockPosition findNearestMapFeature(TagKey<StructureFeature<?, ?>> tagkey, BlockPosition blockposition, int i, boolean flag) { if (!this.serverLevelData.worldGenSettings().generateFeatures()) { // CraftBukkit return null; } else { IRegistry<StructureFeature<?, ?>> iregistry = getLevel().registryAccess().registryOrThrow(IRegistry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY); Holder<StructureFeature<?, ?>> var3 = iregistry.getHolderOrThrow(iregistry.getResourceKey(iregistry.get(tagkey.location())).orElse(ResourceKey.create(iregistry.key(), tagkey.location()))); Pair<BlockPosition, Holder<StructureFeature<?, ?>>> pair = this.getChunkSource().getGenerator().findNearestMapFeature(this, (HolderSet) HolderSet.direct(var3), blockposition, i, flag); return pair != null ? pair.getFirst() : null; } }
I made a patch which resolves the issue, passes all existing tests, and returns null without throwing an error when the structure cannot be found in the world. But, I'm sure there's a better reason as to why this stopped working initially.
I do see there are a good amount of commits RE: /locate and structures at the moment, (I think it was SPIGOT-7000?), so maybe it was something recently, I haven't had a second to look.
- relates to
-
SPIGOT-7065 World#locateNearestStructure always returns null
- Resolved
-
SPIGOT-7081 Ancient City structure type missing
- Resolved