Uploaded image for project: 'Spigot'
  1. Spigot
  2. SPIGOT-7011

Cannot locate Stronghold with World#locateClosestStructure()

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Minor 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. 

       

            DerFrZocker Marvin Rieple
            Andrewcpu ANDREW STEIN
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: