Skip to content

Structure search error #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
uauawa opened this issue Mar 28, 2025 · 0 comments
Open

Structure search error #9

uauawa opened this issue Mar 28, 2025 · 0 comments

Comments

@uauawa
Copy link

uauawa commented Mar 28, 2025

  • There is a 1 in 10 chance that you will be misjudged when using this code to find an end city:
   private static List<BlockPos> locateStructure(Seed seed, Feature feature, EndCityMode endCityMode, BlockPos center, int radius, int maxResults) {
        Dimension dimension = getDimension(feature);
        MCVersion mcVersion = seed.version;
        Structure<?, ?> structure = getStructure(feature, mcVersion);
        if (structure == null) return null;
        BiomeSource biomeSource = BiomeSource.of(dimension, mcVersion, seed.seed);
        if (!structure.isValidDimension(biomeSource.getDimension()))
            return null;
        List<BPos> structurePos = locateStructures(structure, new BPos(center.getX(), center.getY(), center.getZ()), endCityMode, radius, maxResults, new ChunkRand(), biomeSource, TerrainGenerator.of(biomeSource));

        return toBlockPosList(structurePos);
    }

private static List<BPos> locateStructures(Structure<?, ?> structure, BPos center, EndCityMode endCityMode, int radius, int maxResults, ChunkRand chunkRand, BiomeSource source, TerrainGenerator terrainGenerator) {
        List<BPos> result = new ArrayList<>();
        if (structure instanceof EndCity endCity) {
            SpiralIterator<CPos> spiralIterator = new SpiralIterator<>(new CPos(center.getX() >> 4, center.getZ() >> 4), new CPos(radius, radius), (x, y, z) -> new CPos(x, z));

            StreamSupport.stream(spiralIterator.spliterator(), false)
                    .filter(cPos -> {
                        com.seedfinding.mcfeature.Feature.Data<?> data = endCity.at(cPos.getX(), cPos.getZ());
                        EndCityGenerator endCityGenerator = new EndCityGenerator(source.getVersion());
                        return data.testStart(source.getWorldSeed(), chunkRand)
                                && data.testBiome(source)
                                && data.testGenerate(terrainGenerator)
                                && switch (endCityMode) {
                            case OnlyHasShip -> endCityGenerator.generate(terrainGenerator, cPos) && endCityGenerator.hasShip();
                            case OnlyNotShip -> endCityGenerator.generate(terrainGenerator, cPos) && !endCityGenerator.hasShip();
                            case Both -> endCityGenerator.generate(terrainGenerator, cPos);
                        };
                    })
                    .limit(maxResults)
                    .forEach(cPos -> result.add(cPos.toBlockPos().add(9, 0, 9)));
        } else if (structure instanceof RegionStructure<?, ?> regionStructure) {
            int chunkInRegion = regionStructure.getSpacing();
            int regionSize = chunkInRegion * 16;

            final int border = 30_000_000;
            SpiralIterator<RPos> spiralIterator = new SpiralIterator<>(center.toRegionPos(regionSize), new BPos(-border, 0, -border).toRegionPos(regionSize), new BPos(border, 0, border).toRegionPos(regionSize), 1, (x, y, z) -> new RPos(x, z, regionSize));


            StreamSupport.stream(spiralIterator.spliterator(), false)
                    .map(rPos -> regionStructure.getInRegion(source.getWorldSeed(), rPos.getX(), rPos.getZ(), chunkRand))
                    .filter(Objects::nonNull)
                    .filter(cPos -> (regionStructure.canSpawn(cPos, source)) && (terrainGenerator == null || regionStructure.canGenerate(cPos, terrainGenerator)))
                    .limit(maxResults)
                    .forEach(cPos -> result.add(cPos.toBlockPos().add(9, 0, 9)));
        } else {
            if (structure instanceof Stronghold strongholdStructure) {
                CPos currentChunkPos = center.toChunkPos();
                int squaredDistance = Integer.MAX_VALUE;


                for (CPos stronghold : strongholdStructure.getAllStarts(source, chunkRand)) {
                    if (result.size() >= maxResults) {
                        break;
                    }
                    int newSquaredDistance = (currentChunkPos.getX() - stronghold.getX()) * (currentChunkPos.getX() - stronghold.getX()) + (currentChunkPos.getZ() - stronghold.getZ()) * (currentChunkPos.getZ() - stronghold.getZ());
                    if (newSquaredDistance < squaredDistance) {
                        squaredDistance = newSquaredDistance;
                        result.clear();
                        result.add(stronghold.toBlockPos().add(9, 0, 9));
                    }
                }
            } else if (structure instanceof Mineshaft mineshaft) {
                SpiralIterator<CPos> spiralIterator = new SpiralIterator<>(new CPos(center.getX() >> 4, center.getZ() >> 4), new CPos(radius, radius), (x, y, z) -> new CPos(x, z));

                StreamSupport.stream(spiralIterator.spliterator(), false)
                        .filter(cPos -> {
                            com.seedfinding.mcfeature.Feature.Data<Mineshaft> data = mineshaft.at(cPos.getX(), cPos.getZ());
                            return data.testStart(source.getWorldSeed(), chunkRand) && data.testBiome(source) && data.testGenerate(terrainGenerator);
                        })
                        .limit(maxResults)
                        .forEach(cPos -> result.add(cPos.toBlockPos().add(9, 0, 9)));
            }
        }

        return result;
    }


    private static Dimension getDimension(Feature feature) {
        return switch (feature) {
            case buried_treasure -> Dimension.OVERWORLD;
            case mansion -> Dimension.OVERWORLD;
            case stronghold -> Dimension.OVERWORLD;
            case nether_fortress -> Dimension.NETHER;
            case ocean_monument -> Dimension.OVERWORLD;
            case bastion_remnant -> Dimension.NETHER;
            case slime_chunk -> Dimension.OVERWORLD;
            case village -> Dimension.OVERWORLD;
            case mineshaft -> Dimension.OVERWORLD;
            case end_city -> Dimension.END;
            case desert_pyramid -> Dimension.OVERWORLD;
            default -> Dimension.OVERWORLD;
        };
    }

    private static boolean checkIfInDimension(Dimension dimension) {
        return switch (dimension) {
            case OVERWORLD -> (PlayerUtils.getDimension() == meteordevelopment.meteorclient.utils.world.Dimension.Overworld);
            case NETHER -> (PlayerUtils.getDimension() == meteordevelopment.meteorclient.utils.world.Dimension.Nether);
            case END -> (PlayerUtils.getDimension() == meteordevelopment.meteorclient.utils.world.Dimension.End);
        };
    }

    private static Structure<?, ?> getStructure(Feature feature, MCVersion version) {
        return switch (feature) {
            case buried_treasure -> new BuriedTreasure(version);
            case mansion -> new Mansion(version);
            case stronghold -> new Stronghold(version);
            case nether_fortress -> new Fortress(version);
            case ocean_monument -> new Monument(version);
            case bastion_remnant -> new BastionRemnant(version);
            case end_city -> new EndCity(version);
            case village -> new Village(version);
            case mineshaft -> new Mineshaft(version);
            case desert_pyramid -> new DesertPyramid(version);
            default -> null;
        };
    }
    
    private static List<BlockPos> toBlockPosList(List<BPos> posList) {
        List<BlockPos> blockPosList = new ArrayList<>();
        for (BPos pos : posList) {
            blockPosList.add(new BlockPos(pos.getX(), pos.getY(), pos.getZ()));
        }
        return blockPosList;
    }

Seed: -3396536410594980164, Location: -3428 60-13070.

Judging from the seedMap, the location below 1.18.2 will refresh the end city, but above 1.18.2 is useless, I also tried to change the MCVersion of BiomeSource, but the result remains the same, so I suspect that it is an API problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant