[SPIGOT-7011] Cannot locate Stronghold with World#locateClosestStructure() Created: 27/Apr/22 Updated: 25/Dec/24 Resolved: 01/Jul/22 |
|
Status: | Resolved |
Project: | Spigot |
Component/s: | None |
Affects Version/s: | None |
Fix Version/s: | None |
Type: | Bug | Priority: | Minor |
Reporter: | ANDREW STEIN | Assignee: | Marvin Rieple |
Resolution: | Fixed | Votes: | 1 |
Labels: | findNearestMapFeature, locateClosestStructure | ||
Environment: |
|
Attachments: |
![]() |
||||||||||||
Issue Links: |
|
||||||||||||
Version: | 3482-Spigot-42b6152-e87f2e3 (MC: 1.18.2) (Implementing API version 1.18-R0.1-SNAPSHOT) | ||||||||||||
Guidelines Read: | Yes |
Description |
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:
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
|
Comments |
Comment by Marvin Rieple [ 18/Jun/22 ] |
Made a PR for this: craftbukkit#1073 |
Comment by Doc [ 27/Apr/22 ] |
The NMS method in WorldServer its the same used in the command, the difference is for get the "TagKey<StructureFeature<?, ?>>" used in the command vs CB. |
Comment by ANDREW STEIN [ 27/Apr/22 ] |
Why doesn't the locateClosestStructure code use the same underlying NMS code for /locate? |