├── .editorconfig ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── crash_report.yml │ └── feature_request.md ├── assets │ ├── curseforge │ │ └── description.md │ ├── images │ │ ├── logo │ │ │ └── logo.png │ │ ├── structure_spread_settings.webp │ │ ├── structures_search.webp │ │ ├── structures_settings.webp │ │ ├── structures_structure_biome_blacklist.webp │ │ └── structurify_configuration.webp │ └── modrinth │ │ └── description.md ├── scripts │ ├── generate-publish-matrix.sh │ ├── generate-run-matrix.sh │ ├── get-modrinth-dependency-url.sh │ ├── parse-changelog.sh │ ├── parse-gradle-properties.sh │ └── run-server.sh └── workflows │ ├── build.yml │ ├── clear-cache.yml │ └── publish.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE.txt ├── Makefile ├── README.md ├── buildSrc ├── build.gradle.kts └── src │ └── main │ └── kotlin │ ├── build-extensions.kt │ ├── multiloader-common.gradle.kts │ └── multiloader-loader.gradle.kts ├── common ├── build.gradle.kts ├── gradle.properties └── src │ └── main │ ├── java │ └── com │ │ └── faboslav │ │ └── structurify │ │ └── common │ │ ├── Structurify.java │ │ ├── StructurifyClient.java │ │ ├── api │ │ ├── StructurifyRandomSpreadStructurePlacement.java │ │ ├── StructurifyStructure.java │ │ └── StructurifyStructurePlacement.java │ │ ├── checks │ │ ├── JigsawStructureBiomeCheck.java │ │ ├── JigsawStructureFlatnessCheck.java │ │ └── StructureDistanceFromWorldCenterCheck.java │ │ ├── commands │ │ └── DumpCommand.java │ │ ├── config │ │ ├── StructurifyConfig.java │ │ ├── StructurifyConfigLoader.java │ │ ├── client │ │ │ ├── api │ │ │ │ ├── controller │ │ │ │ │ ├── BiomeStringController.java │ │ │ │ │ ├── DualController.java │ │ │ │ │ ├── StructureButtonController.java │ │ │ │ │ ├── builder │ │ │ │ │ │ ├── BiomeStringControllerBuilder.java │ │ │ │ │ │ ├── DualControllerBuilder.java │ │ │ │ │ │ └── StructureButtonControllerBuilder.java │ │ │ │ │ └── element │ │ │ │ │ │ ├── BiomeStringControllerElement.java │ │ │ │ │ │ └── DualControllerElement.java │ │ │ │ └── option │ │ │ │ │ ├── HolderOption.java │ │ │ │ │ └── OptionPair.java │ │ │ └── gui │ │ │ │ ├── StructureConfigScreen.java │ │ │ │ ├── StructureSetsConfigScreen.java │ │ │ │ ├── StructuresConfigScreen.java │ │ │ │ ├── StructurifyConfigScreen.java │ │ │ │ ├── StructurifyConfigScreenState.java │ │ │ │ └── widget │ │ │ │ ├── DynamicGridWidget.java │ │ │ │ └── ImageButtonWidget.java │ │ └── data │ │ │ ├── StructureData.java │ │ │ ├── StructureSetData.java │ │ │ └── WorldgenDataProvider.java │ │ ├── events │ │ ├── base │ │ │ ├── CancellableEventHandler.java │ │ │ └── EventHandler.java │ │ └── common │ │ │ ├── LoadConfigEvent.java │ │ │ └── UpdateRegistriesEvent.java │ │ ├── mixin │ │ ├── AbstractWidgetInvoker.java │ │ ├── ChunkGeneratorMixin.java │ │ ├── LocateCommandMixin.java │ │ ├── ResourcePackManagerAccessor.java │ │ ├── WorldOpenFlowsMixin.java │ │ ├── compat │ │ │ └── RepurposedStructuresModifySpreadMixin.java │ │ ├── plugin │ │ │ └── StructurifyMixinPlugin.java │ │ ├── structure │ │ │ ├── StructureMixin.java │ │ │ ├── jigsaw │ │ │ │ ├── JigsawStructureMixin.java │ │ │ │ └── MaxDistanceFromCenterAccessor.java │ │ │ └── placement │ │ │ │ ├── RandomSpreadStructurePlacementMixin.java │ │ │ │ └── StructurePlacementMixin.java │ │ └── yacl │ │ │ ├── CategoryTabAccessor.java │ │ │ ├── SearchFieldWidgetInvoker.java │ │ │ └── YACLScreenMixin.java │ │ ├── modcompat │ │ ├── GlobalPacksCompat.java │ │ ├── ModChecker.java │ │ ├── ModCompat.java │ │ ├── OpenLoaderCompat.java │ │ └── TerraCompat.java │ │ ├── platform │ │ ├── PlatformCompat.java │ │ ├── PlatformHelper.java │ │ ├── PlatformHooks.java │ │ └── PlatformResourcePackProvider.java │ │ ├── registry │ │ ├── StructurifyRegistryManagerProvider.java │ │ ├── StructurifyRegistryUpdater.java │ │ └── StructurifyResourcePackProvider.java │ │ └── util │ │ ├── LanguageUtil.java │ │ └── RandomSpreadUtil.java │ └── resources │ ├── assets │ └── structurify │ │ ├── lang │ │ └── en_us.json │ │ └── textures │ │ └── gui │ │ └── config │ │ └── images │ │ ├── biomes │ │ ├── badlands.png │ │ ├── badlands_plateau.png │ │ ├── bamboo_jungle.png │ │ ├── basalt_deltas.png │ │ ├── beach.png │ │ ├── birch_forest.png │ │ ├── cherry_grove.png │ │ ├── cold_ocean.png │ │ ├── crimson_forest.png │ │ ├── dark_forest.png │ │ ├── deep_cold_ocean.png │ │ ├── deep_dark.png │ │ ├── deep_frozen_ocean.png │ │ ├── deep_lukewarm_ocean.png │ │ ├── deep_ocean.png │ │ ├── deep_warm_ocean.png │ │ ├── desert.png │ │ ├── desert_lakes.png │ │ ├── dripstone_caves.png │ │ ├── end_barrens.png │ │ ├── end_highlands.png │ │ ├── end_midlands.png │ │ ├── eroded_badlands.png │ │ ├── flower_forest.png │ │ ├── forest.png │ │ ├── frozen_ocean.png │ │ ├── frozen_peaks.png │ │ ├── frozen_river.png │ │ ├── grove.png │ │ ├── ice_spikes.png │ │ ├── jagged_peaks.png │ │ ├── jungle.png │ │ ├── lukewarm_ocean.png │ │ ├── lush_caves.png │ │ ├── mangrove_swamp.png │ │ ├── meadow.png │ │ ├── mountain_edge.png │ │ ├── mushroom_fields.png │ │ ├── nether_wastes.png │ │ ├── ocean.png │ │ ├── old_growth_birch_forest.png │ │ ├── old_growth_pine_taiga.png │ │ ├── old_growth_spruce_taiga.png │ │ ├── plains.png │ │ ├── river.png │ │ ├── savanna.png │ │ ├── savanna_plateau.png │ │ ├── small_end_islands.png │ │ ├── snowy_beach.png │ │ ├── snowy_plains.png │ │ ├── snowy_slopes.png │ │ ├── snowy_taiga.png │ │ ├── soul_sand_valley.png │ │ ├── sparse_jungle.png │ │ ├── stony_peaks.png │ │ ├── stony_shore.png │ │ ├── sunflower_plains.png │ │ ├── swamp.png │ │ ├── taiga.png │ │ ├── the_end.png │ │ ├── the_void.png │ │ ├── unknown.png │ │ ├── warm_ocean.png │ │ ├── warped_forest.png │ │ ├── windswept_forest.png │ │ ├── windswept_gravelly_hills.png │ │ ├── windswept_hills.png │ │ ├── windswept_savanna.png │ │ └── wooded_badlands.png │ │ └── buttons │ │ ├── structure_sets.webp │ │ └── structures.webp │ ├── catalogue_background.png │ ├── catalogue_icon.png │ ├── icon.png │ └── structurify-common.mixins.json ├── fabric ├── build.gradle.kts ├── gradle.properties └── src │ └── main │ ├── java │ └── com │ │ └── faboslav │ │ └── structurify │ │ └── fabric │ │ ├── StructurifyFabric.java │ │ ├── StructurifyFabricClient.java │ │ ├── modcompat │ │ ├── CatalogueCompat.java │ │ ├── GlobalDatapacksCompat.java │ │ └── ModMenuCompat.java │ │ └── platform │ │ ├── FabricPlatformCompat.java │ │ ├── FabricPlatformHelper.java │ │ └── FabricPlatformResourcePackProvider.java │ └── resources │ ├── META-INF │ └── services │ │ ├── com.faboslav.structurify.common.platform.PlatformCompat │ │ ├── com.faboslav.structurify.common.platform.PlatformHelper │ │ └── com.faboslav.structurify.common.platform.PlatformResourcePackProvider │ ├── fabric.mod.json │ └── structurify-fabric.mixins.json ├── forge ├── build.gradle.kts ├── gradle.properties └── src │ └── main │ ├── java │ └── com │ │ └── faboslav │ │ └── structurify │ │ └── forge │ │ ├── StructurifyForge.java │ │ ├── StructurifyForgeClient.java │ │ ├── mixin │ │ └── compat │ │ │ └── StructureGelApiModifySpreadMixin.java │ │ └── platform │ │ ├── ForgePlatformCompat.java │ │ ├── ForgePlatformHelper.java │ │ └── ForgePlatformResourcePackProvider.java │ └── resources │ ├── META-INF │ ├── mods.toml │ └── services │ │ ├── com.faboslav.structurify.common.platform.PlatformCompat │ │ ├── com.faboslav.structurify.common.platform.PlatformHelper │ │ └── com.faboslav.structurify.common.platform.PlatformResourcePackProvider │ ├── pack.mcmeta │ └── structurify-forge.mixins.json ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── neoforge ├── build.gradle.kts ├── gradle.properties └── src │ └── main │ ├── java │ └── com │ │ └── faboslav │ │ └── structurify │ │ └── neoforge │ │ ├── StructurifyNeoForge.java │ │ ├── StructurifyNeoForgeClient.java │ │ └── platform │ │ ├── NeoForgePlatformCompat.java │ │ ├── NeoForgePlatformHelper.java │ │ └── NeoForgePlatformResourcePackProvider.java │ └── resources │ ├── META-INF │ ├── neoforge.mods.toml │ └── services │ │ ├── com.faboslav.structurify.common.platform.PlatformCompat │ │ ├── com.faboslav.structurify.common.platform.PlatformHelper │ │ └── com.faboslav.structurify.common.platform.PlatformResourcePackProvider │ ├── pack.mcmeta │ └── structurify-neoforge.mixins.json ├── settings.gradle.kts ├── stonecutter.gradle.kts └── versions ├── 1.20.1 └── gradle.properties ├── 1.21.1 └── gradle.properties ├── 1.21.3 └── gradle.properties ├── 1.21.4 └── gradle.properties └── 1.21.5 └── gradle.properties /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: Faboslav 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: faboslav 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 'Bug Report' 2 | description: 'Use this template if you want to report a new bug' 3 | labels: [ "bug" ] 4 | assignees: 5 | - Faboslav 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Thanks for taking the time to fill out this bug report! Anyhow before you take your time answering all of the question please make sure of the following: 11 | - Are you sure that there is not already reported same or similar bug? You can try to use the [search](https://github.com/Faboslav/variants-and-ventures/issues). 12 | - Are you using the latest version of the mod? You can find the latest version [here](https://github.com/Faboslav/variants-and-ventures/releases). 13 | - type: input 14 | id: minecraft-version 15 | attributes: 16 | label: 'Minecraft version information' 17 | description: 'Please provide the exact minecraft version that you are using.' 18 | placeholder: 'Example: 1.19.2' 19 | validations: 20 | required: true 21 | - type: dropdown 22 | id: mod-loader 23 | attributes: 24 | label: 'Mod loader information' 25 | description: 'Please choose the mod loader that you are using.' 26 | options: 27 | - Fabric 28 | - Quilt 29 | - Forge 30 | - NeoForge 31 | validations: 32 | required: true 33 | - type: input 34 | id: mod-loader-version 35 | attributes: 36 | label: 'Mod loader version information' 37 | description: 'Please provide the exact mod loader version that you are using.' 38 | placeholder: 'Example: 0.13.3 (Fabric) or 40.0.32 (Forge)' 39 | validations: 40 | required: true 41 | - type: input 42 | id: mod-version 43 | attributes: 44 | label: 'Mod version information' 45 | description: 'Please provide the exact mod version that you are using.' 46 | placeholder: 'Example: 1.0.0' 47 | validations: 48 | required: true 49 | - type: textarea 50 | id: expected-behaviour 51 | attributes: 52 | label: 'Expected Behavior' 53 | description: 'What did you expect to happen?' 54 | placeholder: 'Example: The mob should move.' 55 | validations: 56 | required: true 57 | - type: textarea 58 | id: actual-behaviour 59 | attributes: 60 | label: 'Actual Behavior' 61 | description: 'What did actually happen?' 62 | placeholder: 'Example: The mob does not move.' 63 | validations: 64 | required: true 65 | - type: textarea 66 | id: reproduction-steps 67 | attributes: 68 | label: 'Reproduction Steps' 69 | description: 'Provide information on how to reproduce this bug. Make sure your instructions are minimal and clear.' 70 | placeholder: | 71 | Example: 72 | 1. Spawn Copper Golem using spawn egg 73 | 2. Wait for some action 74 | 3. Nothing happens 75 | validations: 76 | required: true 77 | - type: textarea 78 | id: screenshots-and-files 79 | attributes: 80 | label: 'Screenshots & files' 81 | description: 'If appropriate, add screenshots or other files to help explain your problem.' 82 | placeholder: 'You can attach your files by dragging & dropping them to this textbox.' 83 | validations: 84 | required: false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/crash_report.yml: -------------------------------------------------------------------------------- 1 | name: 'Crash Report' 2 | description: 'Use this template if your game is crashing or failing to start correctly' 3 | labels: [ "crash" ] 4 | assignees: 5 | - Faboslav 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Thanks for taking the time to fill out this crash report! Anyhow before you take your time answering all of the question please make sure of the following: 11 | - Are you sure that there is not already reported same or similar crash? You can try to use the [search](https://github.com/Faboslav/variants-and-ventures/issues). 12 | - Are you using the latest version of the mod? You can find the latest version [here](https://github.com/Faboslav/variants-and-ventures/releases). 13 | - type: input 14 | id: minecraft-version 15 | attributes: 16 | label: 'Minecraft version information' 17 | description: 'Please provide the exact minecraft version that you are using.' 18 | placeholder: 'Example: 1.19.2' 19 | validations: 20 | required: true 21 | - type: dropdown 22 | id: mod-loader 23 | attributes: 24 | label: 'Mod loader information' 25 | description: 'Please choose the mod loader that you are using.' 26 | options: 27 | - Fabric 28 | - Quilt 29 | - Forge 30 | - NeoForge 31 | validations: 32 | required: true 33 | - type: input 34 | id: mod-loader-version 35 | attributes: 36 | label: 'Mod loader version information' 37 | description: 'Please provide the exact mod loader version that you are using.' 38 | placeholder: 'Example: 0.13.3 (Fabric) or 40.0.32 (Forge)' 39 | validations: 40 | required: true 41 | - type: input 42 | id: mod-version 43 | attributes: 44 | label: 'Mod version information' 45 | description: 'Please provide the exact mod version that you are using.' 46 | placeholder: 'Example: 1.0.0' 47 | validations: 48 | required: true 49 | - type: textarea 50 | id: reproduction-steps 51 | attributes: 52 | label: 'Reproduction Steps' 53 | description: 'Provide information on how to reproduce this bug. Make sure your instructions are minimal and clear.' 54 | placeholder: | 55 | Example: 56 | 1. Spawn mob using spawn egg 57 | 2. Wait for some action 58 | 3. Nothing happens 59 | validations: 60 | required: true 61 | - type: textarea 62 | id: report 63 | attributes: 64 | label: 'Crash Report and latest.log' 65 | description: 'Latest crash report generated by your minecraft client. Crash report file should be located in `crash-report` directory and latest.log file should be located in `logs` directory. Uploading both of these files is critical in resolving your issue!' 66 | placeholder: 'You can attach your crash report and latest.log by dragging & dropping them to this textbox.' 67 | validations: 68 | required: true 69 | - type: textarea 70 | id: screenshots-and-files 71 | attributes: 72 | label: 'Additional information' 73 | description: 'List of other mods that you are using. If appropriate, add screenshots or other files to help explain your problem.' 74 | placeholder: 'You can attach your files by dragging & dropping them to this textbox.' 75 | validations: 76 | required: false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request about: Suggest an idea for this project title: '' 3 | labels: feature assignees: 'Faboslav' 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. -------------------------------------------------------------------------------- /.github/assets/images/logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/.github/assets/images/logo/logo.png -------------------------------------------------------------------------------- /.github/assets/images/structure_spread_settings.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/.github/assets/images/structure_spread_settings.webp -------------------------------------------------------------------------------- /.github/assets/images/structures_search.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/.github/assets/images/structures_search.webp -------------------------------------------------------------------------------- /.github/assets/images/structures_settings.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/.github/assets/images/structures_settings.webp -------------------------------------------------------------------------------- /.github/assets/images/structures_structure_biome_blacklist.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/.github/assets/images/structures_structure_biome_blacklist.webp -------------------------------------------------------------------------------- /.github/assets/images/structurify_configuration.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/.github/assets/images/structurify_configuration.webp -------------------------------------------------------------------------------- /.github/scripts/generate-publish-matrix.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | allowed_mod_loaders=$1 4 | allowed_versions=$2 5 | 6 | echo ${allowed_mod_loaders}; 7 | echo ${allowed_versions}; 8 | 9 | IFS=',' read -r -a allowed_mod_loaders_array <<< "${allowed_mod_loaders//[\[\]\']/}" 10 | IFS=',' read -r -a allowed_versions_array <<< "${allowed_versions//[\[\]\']/}" 11 | 12 | matrix_content="{\"include\":[" 13 | enabled_platforms=$(awk -F= '/stonecutter_enabled_platforms/{print $2}' gradle.properties | tr -d ' ') 14 | 15 | for platform in $(echo $enabled_platforms | tr ',' ' '); do 16 | if [[ " ${allowed_mod_loaders_array[@]} " =~ " ${platform} " ]]; then 17 | versions=$(awk -F= '/stonecutter_enabled_'$platform'_versions/{print $2}' gradle.properties | tr -d ' ') 18 | for version in $(echo $versions | tr ',' ' '); do 19 | if [[ " ${allowed_versions_array[@]} " =~ " ${version} " ]]; then 20 | if [[ "$platform" == "fabric" ]]; then 21 | supported_mod_loaders="\"fabric\",\"quilt\"" 22 | else 23 | supported_mod_loaders="\"$platform\"" 24 | fi 25 | 26 | matrix_entry="{\"mod_loader\":\"$platform\",\"version\":\"$version\",\"supported_mod_loaders\":[$supported_mod_loaders]}," 27 | matrix_content+="$matrix_entry" 28 | fi 29 | done 30 | fi 31 | done 32 | 33 | matrix_content="${matrix_content%,}]}" 34 | echo "Generated matrix: $matrix_content" 35 | echo "::set-output name=matrix::$matrix_content" -------------------------------------------------------------------------------- /.github/scripts/generate-run-matrix.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | matrix_content="{\"include\":[" 4 | enabled_platforms=$(awk -F= '/stonecutter_enabled_platforms/{print $2}' gradle.properties | tr -d ' ') 5 | 6 | for platform in $(echo $enabled_platforms | tr ',' ' '); do 7 | if [[ "$platform" == "forge" ]]; then 8 | mod_loader_alias="lexforge" 9 | else 10 | mod_loader_alias="$platform" 11 | fi 12 | 13 | if [[ "$platform" == "neoforge" ]]; then 14 | mod_loader_modrinth="forge" 15 | else 16 | mod_loader_modrinth="$platform" 17 | fi 18 | 19 | versions=$(awk -F= '/stonecutter_enabled_'$platform'_versions/{print $2}' gradle.properties | tr -d ' ') 20 | for version in $(echo $versions | tr ',' ' '); do 21 | matrix_entry="{\"mod_loader\":\"$platform\",\"mod_loader_alias\":\"$mod_loader_alias\",\"mod_loader_modrinth\":\"$mod_loader_modrinth\",\"version\":\"$version\"}," 22 | matrix_content+="$matrix_entry" 23 | done 24 | done 25 | 26 | matrix_content="${matrix_content%,}]}" 27 | echo "Generated matrix: $matrix_content" 28 | echo "::set-output name=matrix::$matrix_content" -------------------------------------------------------------------------------- /.github/scripts/get-modrinth-dependency-url.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Variables 4 | MOD_SLUG=$1 5 | MOD_VERSION=$2 6 | LOADER=$3 7 | 8 | # Fetch version information from Modrinth API 9 | API_URL="https://api.modrinth.com/v2/project/${MOD_SLUG}/version" 10 | VERSION_DATA=$(curl -s "$API_URL") 11 | 12 | # Sanitize VERSION_DATA by removing any control characters 13 | SANITIZED_DATA=$(echo "$VERSION_DATA" | tr -d '\000-\031') 14 | 15 | # Check if SANITIZED_DATA is not empty 16 | if [ -z "$SANITIZED_DATA" ]; then 17 | echo "No data received from Modrinth API." 18 | exit 1 19 | fi 20 | 21 | # Extract the download URL for the specified loader and version 22 | DOWNLOAD_URL=$(echo "$SANITIZED_DATA" | jq -r --arg loader "$LOADER" --arg mod_version "$MOD_VERSION" \ 23 | '.[] | select(.version_number == $mod_version) | select(.loaders | index($loader)) | .files[] | select(.primary == true) | .url') 24 | 25 | # Output the download URL 26 | if [ -n "$DOWNLOAD_URL" ]; then 27 | echo "$DOWNLOAD_URL" 28 | else 29 | echo "No matching file found for ${MOD_SLUG} version ${MOD_VERSION} with loader ${LOADER}." 30 | exit 1 31 | fi -------------------------------------------------------------------------------- /.github/scripts/parse-changelog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | tag=$1 4 | changelog=$(cat CHANGELOG.md) 5 | 6 | # Extract the changelog section for the specified tag 7 | list=$(echo "$changelog" | sed -n "/^## $tag/,/^## [0-9]/p" | sed -e '1d;$d') 8 | 9 | # Remove the first blank line if it exists 10 | list=$(echo "$list" | sed -e '1{/^$/d;}') 11 | 12 | echo "$list" > RELEASE_CHANGELOG.md -------------------------------------------------------------------------------- /.github/scripts/parse-gradle-properties.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | version=${1:-} 4 | 5 | parse_properties_file() { 6 | local file=$1 7 | while IFS='=' read -r key value; do 8 | key=$(echo "$key" | awk '{$1=$1;print}') 9 | value=$(echo "$value" | awk '{$1=$1;print}') 10 | 11 | if [[ -z "$key" || "$key" =~ ^# || "$key" == "org.gradle.jvmargs" ]]; then 12 | continue 13 | fi 14 | 15 | key=$(echo "$key" | tr '[:lower:]' '[:upper:]' | tr -c '[:alnum:]' '_') 16 | key=$(echo "$key" | sed 's/_$//') 17 | 18 | echo "${key}=${value}" 19 | echo "${key}=${value}" >> "$GITHUB_OUTPUT" 20 | done < "$file" 21 | } 22 | 23 | parse_properties_file gradle.properties 24 | 25 | if [[ -n "$version" ]]; then 26 | parse_properties_file "versions/${version}/gradle.properties" 27 | fi -------------------------------------------------------------------------------- /.github/scripts/run-server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mod_loader=$1 4 | version=$2 5 | 6 | mkdir -p $mod_loader/versions/$version/run && echo "eula=true" > $mod_loader/versions/$version/run/eula.txt 7 | 8 | ./gradlew $mod_loader:$version:runServer --no-daemon --args="nogui" 2>&1 | tee gradle_server_output.txt & 9 | 10 | SUCCESS_PATTERN='For help, type "help"' 11 | ERROR_PATTERNS=( 12 | 'For more details see the full crash report file' 13 | ' end of report ' 14 | 'Failed download after 3 attempts' 15 | 'Error: Exception in thread' 16 | ) 17 | TIMEOUT=1800 18 | ELAPSED=0 19 | 20 | while [ $ELAPSED -lt $TIMEOUT ]; do 21 | if grep -Eq "$SUCCESS_PATTERN" gradle_server_output.txt; then 22 | pkill -P $$ 23 | exit 0 24 | fi 25 | 26 | for ERROR_PATTERN in "${ERROR_PATTERNS[@]}"; do 27 | if grep -Eq "$ERROR_PATTERN" gradle_server_output.txt; then 28 | pkill -P $$ 29 | exit 1 30 | fi 31 | done 32 | 33 | sleep 1 34 | ELAPSED=$((ELAPSED + 1)) 35 | done 36 | 37 | if [ $ELAPSED -ge $TIMEOUT ]; then 38 | exit 1 39 | fi -------------------------------------------------------------------------------- /.github/workflows/clear-cache.yml: -------------------------------------------------------------------------------- 1 | name: "Clear cache" 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | clear-cache: 8 | runs-on: ubuntu-latest 9 | name: "Clear cache" 10 | timeout-minutes: 60 11 | steps: 12 | - uses: MyAlbum/purge-cache@v2 13 | with: 14 | accessed: true 15 | created: true 16 | max-age: 0 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.ipr 3 | run/ 4 | *.iws 5 | out/ 6 | *.iml 7 | .gradle/ 8 | output/ 9 | bin/ 10 | libs/ 11 | 12 | .classpath 13 | .project 14 | .idea/ 15 | classes/ 16 | .metadata 17 | .vscode 18 | .settings 19 | *.launch 20 | .architectury-transformer 21 | gradle_client_output.txt 22 | gradle_server_output.txt -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.13 2 | 3 | - Fixed crash related to Repurposed Structures compat 4 | 5 | ## 1.0.12 6 | 7 | - A lot of quality of life features like keeping search, scroll position and more 8 | - Added support for biome tags 9 | - Added compatibility with the Open Loader 10 | - Added compatibility with the Terra 11 | - Added "salt" as a configurable field for structure sets 12 | - Added "frequency" as a configurable field for structure sets 13 | - Fixed mod crash related to latest YACL 14 | - Fixed main menu blur (on 1.21.4) 15 | - Fixed error related to initial config creation 16 | - Fixed mod crash related to missing/incorrect translations for biomes 17 | - Increased spacing/separation slider range from 128 to 256 18 | 19 | ## 1.0.11 20 | 21 | - Removed the dev console spam (sorry for the troubles and multiple releases) 22 | 23 | ## 1.0.10 24 | 25 | - Fixed crash related to invalid catalogue compat setup 26 | 27 | ## 1.0.9 28 | 29 | - Fixed typo causing invalid saving and loading of "disable_all_structures" option 30 | - Improved GUI behavior, it should be more clear what is now possible and what is not 31 | - Added new "min structure distance from world center" (min_structure_distance_from_world_center) global setting 32 | - Added new "terrain flatness" check configuration to each structure 33 | - Added new "config_version" property, so migrating between different config versions in the future is more manageable 34 | 35 | ## 1.0.8 36 | 37 | - Fixed critical compatibility issue which prevented structure generation in the non vanilla biomes (for example Blue Skies) 38 | - Structure "biome" field in json is now de/composed based on "whitelisted_biomes" and "blacklisted_biomes" fields instead to possibly avoid the list of 280 biome entries in modded environments 39 | 40 | ## 1.0.7 41 | 42 | - Added compatibility with the Structure Gel API, ensuring that mods like Dungeons Enhanced are now fully affected by all settings 43 | - Fixed a bug in Forge (and possibly NeoForge) where structures were not generating as expected 44 | 45 | ## 1.0.6 46 | 47 | - Improved GUI of structure settings 48 | - Removed biome blacklist in favor of direct biome editing (allowing to add or remove any biome) along with the optional biome check feature 49 | - Fixed incompatibility with Repurposed Structures 50 | 51 | ## 1.0.5 52 | 53 | - Fixed incompatibility with GregTech CEu: Modern and some other mods 54 | - Improved performance up to 50% in some cases by correctly handling registry access 55 | - Prepared infrastructure for caching to possibly enhance performance further 56 | 57 | ## 1.0.4 58 | 59 | - Fixed incompatibility with Placebo/Apothic Enchanting mods 60 | - Improved performance by creating the config screens lazily on demand 61 | 62 | ## 1.0.3 63 | 64 | - Fixed lock on biome blacklist type 65 | - Improved compatibility with other mods 66 | 67 | ## 1.0.2 68 | 69 | - 1.21.1 port 70 | - Improved compatibility with other mods 71 | 72 | ## 1.0.1 73 | 74 | - Fixed crash related to spacing/separation global modifier 75 | - Improved compatibility with other mods 76 | 77 | ## 1.0.0 78 | 79 | - Initial release -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | help: ## Prints help for targets with comments 2 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 3 | 4 | build-project: ## Builds project 5 | ./gradlew build 6 | 7 | build-chiseled: ## Builds project 8 | ./gradlew chiseledBuild 9 | 10 | build-active: ## Builds the active version 11 | ./gradlew buildActiveCommon 12 | ./gradlew buildActiveFabric 13 | ./gradlew buildActiveForge 14 | ./gradlew buildActiveNeoForge 15 | 16 | refresh: ## Refresh dependencies 17 | ./gradlew --refresh-dependencies 18 | 19 | clean-cache: ## Cleans cache 20 | ./gradlew --stop 21 | rm -rf $GRADLE_HOME/caches/transforms-* 22 | rm -rf $GRADLE_HOME/caches/build-cache-* 23 | ./gradlew clean 24 | 25 | stop: ## Stops all deamons 26 | ./gradlew --stop 27 | 28 | gen-sources: ## Generate sources 29 | ./gradlew genSources 30 | 31 | run-fabric-client: ## Runs fabric client 32 | ./gradlew :fabric:1.21.5:runClient 33 | 34 | run-forge-client: ## Runs forge client 35 | ./gradlew :forge:1.20.1:runClient 36 | 37 | run-neoforge-client: ## Runs neoforge client 38 | ./gradlew neoforge:1.21.5:runClient 39 | 40 | run-fabric-server: ## Runs fabric server 41 | ./gradlew fabric:1.21.1:runServer 42 | 43 | run-forge-server: ## Runs forge server 44 | ./gradlew forge:runServer 45 | 46 | run-neoforge-server: ## Runs neoforge server 47 | ./gradlew neoforge:1.21.1:testProductionServer 48 | 49 | nuke: ## Nuke the project 50 | ./gradlew --stop 51 | rm -rf $GRADLE_HOME/caches/transforms-* 52 | rm -rf $GRADLE_HOME/caches/build-cache-* 53 | find . -type d \( -name ".idea" -o -name ".kotlin" -o -name ".gradle" -o -name "build" -o -name "run" \) -exec rm -rf {} + -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | } 4 | 5 | repositories { 6 | mavenCentral() 7 | gradlePluginPortal() 8 | maven("https://maven.kikugie.dev/snapshots") 9 | } 10 | 11 | dependencies { 12 | fun plugin(id: String, version: String) = "$id:$id.gradle.plugin:$version" 13 | 14 | implementation("dev.kikugie:stonecutter:0.6") 15 | } -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/build-extensions.kt: -------------------------------------------------------------------------------- 1 | import dev.kikugie.stonecutter.build.StonecutterBuild 2 | import dev.kikugie.stonecutter.controller.StonecutterController 3 | import org.gradle.api.Project 4 | import org.gradle.api.artifacts.dsl.RepositoryHandler 5 | import org.gradle.kotlin.dsl.* 6 | 7 | val Project.mod: ModData get() = ModData(this) 8 | fun Project.prop(key: String): String? = findProperty(key)?.toString() 9 | fun String.upperCaseFirst() = replaceFirstChar { if (it.isLowerCase()) it.uppercaseChar() else it } 10 | 11 | fun RepositoryHandler.strictMaven(url: String, alias: String, vararg groups: String) = exclusiveContent { 12 | forRepository { maven(url) { name = alias } } 13 | filter { groups.forEach(::includeGroup) } 14 | } 15 | 16 | val Project.stonecutterBuild get() = extensions.getByType() 17 | val Project.stonecutterController get() = extensions.getByType() 18 | 19 | val Project.common get() = requireNotNull(stonecutterBuild.node.sibling("common")) { 20 | "No common project for $project" 21 | } 22 | val Project.commonProject get() = rootProject.project(stonecutterBuild.current.project) 23 | val Project.commonMod get() = commonProject.mod 24 | 25 | val Project.loader: String? get() = prop("loader") 26 | 27 | @JvmInline 28 | value class ModData(private val project: Project) { 29 | val id: String get() = modProp("id") 30 | val name: String get() = modProp("name") 31 | val version: String get() = modProp("version") 32 | val group: String get() = modProp("group") 33 | val author: String get() = modProp("author") 34 | val description: String get() = modProp("description") 35 | val license: String get() = modProp("license") 36 | val mc: String get() = depOrNull("minecraft") ?: project.stonecutterBuild.current.version 37 | 38 | fun propOrNull(key: String) = project.prop(key) 39 | fun prop(key: String) = requireNotNull(propOrNull(key)) { "Missing '$key'" } 40 | fun modPropOrNull(key: String) = project.prop("mod.$key") 41 | fun modProp(key: String) = requireNotNull(modPropOrNull(key)) { "Missing 'mod.$key'" } 42 | fun depOrNull(key: String): String? = project.prop("deps.$key")?.takeIf { it.isNotEmpty() && it != "" } 43 | fun dep(key: String) = requireNotNull(depOrNull(key)) { "Missing 'deps.$key'" } 44 | fun modrinth(name: String, version:String) = "maven.modrinth:$name:$version" 45 | } -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/multiloader-common.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("java") 3 | id("idea") 4 | id("java-library") 5 | } 6 | 7 | version = "${loader}-${commonMod.version}+mc${stonecutterBuild.current.version}" 8 | 9 | base { 10 | archivesName = commonMod.id 11 | } 12 | 13 | java { 14 | toolchain.languageVersion = JavaLanguageVersion.of(commonProject.prop("java.version")!!) 15 | // withSourcesJar() 16 | // withJavadocJar() 17 | } 18 | 19 | repositories { 20 | mavenCentral() 21 | exclusiveContent { 22 | forRepository { 23 | maven("https://repo.spongepowered.org/repository/maven-public") { name = "Sponge" } 24 | } 25 | filter { includeGroupAndSubgroups("org.spongepowered") } 26 | } 27 | 28 | exclusiveContent { 29 | forRepositories( 30 | maven("https://maven.parchmentmc.org") { name = "ParchmentMC" }, 31 | maven("https://maven.neoforged.net/releases") { name = "NeoForge" }, 32 | ) 33 | filter { includeGroup("org.parchmentmc.data") } 34 | } 35 | 36 | maven("https://www.cursemaven.com") 37 | maven("https://api.modrinth.com/maven") { 38 | name = "Modrinth" 39 | content { 40 | includeGroup("maven.modrinth") 41 | } 42 | } 43 | maven("https://maven.terraformersmc.com/releases/") { name = "TerraformersMC" } 44 | exclusiveContent { 45 | forRepository { maven("https://thedarkcolour.github.io/KotlinForForge/") } 46 | filter { includeGroup("thedarkcolour") } 47 | } 48 | maven("https://maven.isxander.dev/releases") 49 | maven("https://maven.isxander.dev/snapshots") 50 | maven("https://maven.quiltmc.org/repository/release") 51 | maven("https://oss.sonatype.org/content/repositories/snapshots") 52 | maven("https://maven.ladysnake.org/releases") { name = "Ladysnake Libs" } 53 | maven("https://maven.theillusivec4.top/") 54 | maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1") 55 | 56 | maven("https://maven.jamieswhiteshirt.com/libs-release") { 57 | content { 58 | includeGroup("com.jamieswhitefshirt") 59 | } 60 | } 61 | 62 | maven("https://maven.blamejared.com") 63 | 64 | maven("https://nexus.resourcefulbees.com/repository/telepathicgrunt/") 65 | 66 | maven { 67 | name = "CodeMC" 68 | url = uri("https://repo.codemc.org/repository/maven-public/") 69 | } 70 | } 71 | 72 | tasks { 73 | processResources { 74 | val expandProps = mapOf( 75 | "javaVersion" to commonMod.propOrNull("java.version"), 76 | "modId" to commonMod.id, 77 | "modName" to commonMod.name, 78 | "modVersion" to commonMod.version, 79 | "modGroup" to commonMod.group, 80 | "modAuthor" to commonMod.author, 81 | "modDescription" to commonMod.description, 82 | "modLicense" to commonMod.license, 83 | "minecraftVersion" to commonMod.propOrNull("minecraft_version"), 84 | "minMinecraftVersion" to commonMod.propOrNull("min_minecraft_version"), 85 | "fabricLoaderVersion" to commonMod.depOrNull("fabric_loader"), 86 | "fabricApiVersion" to commonMod.depOrNull("fabric_api"), 87 | "forgeVersion" to commonMod.depOrNull("forge"), 88 | "neoForgeVersion" to commonMod.depOrNull("neoforge"), 89 | "yaclVersion" to commonMod.depOrNull("yacl"), 90 | "modMenuVersion" to commonMod.depOrNull("mod_menu"), 91 | ).filterValues { it?.isNotEmpty() == true }.mapValues { (_, v) -> v!! } 92 | 93 | val jsonExpandProps = expandProps.mapValues { (_, v) -> v.replace("\n", "\\\\n") } 94 | 95 | filesMatching(listOf("META-INF/mods.toml", "META-INF/neoforge.mods.toml")) { 96 | expand(expandProps) 97 | } 98 | 99 | filesMatching(listOf("pack.mcmeta", "fabric.mod.json", "*.mixins.json")) { 100 | expand(jsonExpandProps) 101 | } 102 | 103 | inputs.properties(expandProps) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/multiloader-loader.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("java") 3 | id("idea") 4 | id("multiloader-common") 5 | } 6 | 7 | val commonJava: Configuration by configurations.creating { 8 | isCanBeResolved = true 9 | } 10 | val commonResources: Configuration by configurations.creating { 11 | isCanBeResolved = true 12 | } 13 | 14 | dependencies { 15 | val commonPath = common.hierarchy.toString() 16 | compileOnly(project(path = commonPath)) 17 | commonJava(project(path = commonPath, configuration = "commonJava")) 18 | commonResources(project(path = commonPath, configuration = "commonResources")) 19 | } 20 | 21 | tasks { 22 | compileJava { 23 | dependsOn(commonJava) 24 | source(commonJava) 25 | } 26 | 27 | processResources { 28 | dependsOn(commonResources) 29 | from(commonResources) 30 | } 31 | } -------------------------------------------------------------------------------- /common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("multiloader-common") 3 | id("fabric-loom") 4 | id("dev.kikugie.j52j") version "2.0" 5 | } 6 | 7 | stonecutter { 8 | const( 9 | "global_packs", 10 | rootProject.project(stonecutter.current.project).property("deps.global_packs").toString() != "" 11 | ) 12 | const("open_loader", rootProject.project(stonecutter.current.project).property("deps.open_loader").toString() != "") 13 | const("yungs_api", rootProject.project(stonecutter.current.project).property("deps.yungs_api").toString() != "") 14 | const( 15 | "repurposed_structures", 16 | rootProject.project(stonecutter.current.project).property("deps.repurposed_structures") 17 | .toString() != "" && rootProject.project(stonecutter.current.project).property("deps.midnight_lib") 18 | .toString() != "" 19 | ) 20 | } 21 | 22 | loom { 23 | mixin { 24 | useLegacyMixinAp = false 25 | } 26 | } 27 | 28 | dependencies { 29 | minecraft(group = "com.mojang", name = "minecraft", version = commonMod.mc) 30 | mappings(loom.layered { 31 | officialMojangMappings() 32 | commonMod.depOrNull("parchment")?.let { parchmentVersion -> 33 | parchment("org.parchmentmc.data:parchment-${commonMod.mc}:$parchmentVersion@zip") 34 | } 35 | }) 36 | 37 | compileOnly("org.spongepowered:mixin:0.8.5") 38 | 39 | "io.github.llamalad7:mixinextras-common:0.4.1".let { 40 | compileOnly(it) 41 | annotationProcessor(it) 42 | } 43 | 44 | modCompileOnly("net.fabricmc:fabric-loader:${commonMod.dep("fabric_loader")}") 45 | modCompileOnly("dev.isxander:yet-another-config-lib:${commonMod.dep("yacl")}-fabric") 46 | 47 | // Global Packs 48 | commonMod.depOrNull("global_packs")?.let { globalPacksVersion -> 49 | if (commonMod.mc == "1.20.1") { 50 | modImplementation(commonMod.modrinth("globalpacks", "${globalPacksVersion}_fabric")) 51 | } else { 52 | modImplementation(commonMod.modrinth("globalpacks", globalPacksVersion)) 53 | } 54 | } 55 | 56 | // Open Loader 57 | commonMod.depOrNull("open_loader")?.let { openLoaderVersion -> 58 | if (commonMod.mc == "1.21.1") { 59 | modImplementation( 60 | group = "net.darkhax.openloader", 61 | name = "openloader-common-${commonMod.mc}", 62 | version = openLoaderVersion 63 | ) 64 | } else { 65 | modImplementation( 66 | group = "net.darkhax.openloader", 67 | name = "OpenLoader-Common-${commonMod.mc}", 68 | version = openLoaderVersion 69 | ) 70 | } 71 | } 72 | 73 | // Terra 74 | commonMod.depOrNull("terra")?.let { terraVersion -> 75 | modImplementation("com.dfsek.terra:fabric:${terraVersion}") 76 | } 77 | 78 | // Yungs api 79 | commonMod.depOrNull("yungs_api_minecraft")?.let { yungsApiMcVersion -> 80 | commonMod.depOrNull("yungs_api")?.let { yungsApiVersion -> 81 | modImplementation("com.yungnickyoung.minecraft.yungsapi:YungsApi:$yungsApiMcVersion-Fabric-$yungsApiVersion") 82 | } 83 | } 84 | 85 | // Repurposed Structures 86 | commonMod.depOrNull("repurposed_structures")?.let { repurposedStructuresVersion -> 87 | modImplementation("com.telepathicgrunt:RepurposedStructures:${repurposedStructuresVersion}-fabric") 88 | } 89 | } 90 | 91 | val commonJava: Configuration by configurations.creating { 92 | isCanBeResolved = false 93 | isCanBeConsumed = true 94 | } 95 | 96 | val commonResources: Configuration by configurations.creating { 97 | isCanBeResolved = false 98 | isCanBeConsumed = true 99 | } 100 | 101 | artifacts { 102 | afterEvaluate { 103 | val mainSourceSet = sourceSets.main.get() 104 | mainSourceSet.java.sourceDirectories.files.forEach { 105 | add(commonJava.name, it) 106 | } 107 | mainSourceSet.resources.sourceDirectories.files.forEach { 108 | add(commonResources.name, it) 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /common/gradle.properties: -------------------------------------------------------------------------------- 1 | loader=common -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/Structurify.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common; 2 | 3 | import com.faboslav.structurify.common.config.StructurifyConfig; 4 | import com.faboslav.structurify.common.config.StructurifyConfigLoader; 5 | import com.faboslav.structurify.common.events.common.LoadConfigEvent; 6 | import com.faboslav.structurify.common.events.common.UpdateRegistriesEvent; 7 | import com.faboslav.structurify.common.modcompat.ModChecker; 8 | import com.faboslav.structurify.common.registry.StructurifyRegistryUpdater; 9 | import net.minecraft.resources.ResourceLocation; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | @SuppressWarnings("all") 14 | public final class Structurify 15 | { 16 | public static final String MOD_ID = "structurify"; 17 | private static final Logger LOGGER = LoggerFactory.getLogger(Structurify.MOD_ID); 18 | private static final StructurifyConfig CONFIG = new StructurifyConfig(); 19 | 20 | public static String makeStringID(String name) { 21 | return MOD_ID + ":" + name; 22 | } 23 | 24 | public static Logger getLogger() { 25 | return LOGGER; 26 | } 27 | 28 | public static StructurifyConfig getConfig() { 29 | return CONFIG; 30 | } 31 | 32 | public static ResourceLocation makeId(String path) { 33 | //? >=1.21 { 34 | return ResourceLocation.tryBuild( 35 | MOD_ID, 36 | path 37 | ); 38 | //?} else { 39 | /*return new ResourceLocation( 40 | MOD_ID, 41 | path 42 | ); 43 | *///?} 44 | } 45 | 46 | public static ResourceLocation makeNamespacedId(String id) { 47 | //? >=1.21 { 48 | return ResourceLocation.parse( 49 | id 50 | ); 51 | //?} else { 52 | /*return new ResourceLocation( 53 | id 54 | ); 55 | *///?} 56 | } 57 | 58 | public static void init() { 59 | Structurify.getConfig().create(); 60 | ModChecker.setupModCompat(); 61 | 62 | LoadConfigEvent.EVENT.addListener(StructurifyConfigLoader::loadConfig); 63 | UpdateRegistriesEvent.EVENT.addListener(StructurifyRegistryUpdater::updateRegistries); 64 | } 65 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/StructurifyClient.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common; 2 | 3 | import com.faboslav.structurify.common.config.client.gui.StructurifyConfigScreen; 4 | import net.minecraft.client.gui.screens.Screen; 5 | import org.jetbrains.annotations.Nullable; 6 | 7 | public final class StructurifyClient 8 | { 9 | private static StructurifyConfigScreen CONFIG_SCREEN; 10 | 11 | public static void init() { 12 | } 13 | 14 | public static StructurifyConfigScreen getConfigScreen(Screen screen) { 15 | if (CONFIG_SCREEN == null) { 16 | CONFIG_SCREEN = new StructurifyConfigScreen(screen); 17 | } 18 | 19 | return CONFIG_SCREEN; 20 | } 21 | 22 | @Nullable 23 | public static StructurifyConfigScreen getConfigScreen() { 24 | return CONFIG_SCREEN; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/api/StructurifyRandomSpreadStructurePlacement.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.api; 2 | 3 | public interface StructurifyRandomSpreadStructurePlacement extends StructurifyStructurePlacement 4 | { 5 | int structurify$getOriginalSpacing(); 6 | 7 | int structurify$getOriginalSeparation(); 8 | } 9 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/api/StructurifyStructure.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.api; 2 | 3 | import net.minecraft.core.HolderSet; 4 | import net.minecraft.resources.ResourceLocation; 5 | import net.minecraft.world.level.biome.Biome; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | public interface StructurifyStructure 9 | { 10 | void structurify$setStructureIdentifier(@Nullable ResourceLocation structureSetIdentifier); 11 | 12 | @Nullable 13 | ResourceLocation structurify$getStructureIdentifier(); 14 | 15 | void structurify$setStructureBiomes(@Nullable HolderSet biomeHolderSet); 16 | 17 | @Nullable 18 | HolderSet structurify$getStructureBiomes(); 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/api/StructurifyStructurePlacement.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.api; 2 | 3 | import net.minecraft.resources.ResourceLocation; 4 | import org.jetbrains.annotations.Nullable; 5 | 6 | public interface StructurifyStructurePlacement 7 | { 8 | void structurify$setStructureSetIdentifier(@Nullable ResourceLocation structureSetIdentifier); 9 | 10 | @Nullable 11 | ResourceLocation structurify$getStructureSetIdentifier(); 12 | 13 | int structurify$getOriginalSalt(); 14 | 15 | float structurify$getOriginalFrequency(); 16 | } 17 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/checks/JigsawStructureBiomeCheck.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.checks; 2 | 3 | import com.faboslav.structurify.common.config.data.StructureData; 4 | import net.minecraft.core.BlockPos; 5 | import net.minecraft.core.Holder; 6 | import net.minecraft.core.QuartPos; 7 | import net.minecraft.world.level.ChunkPos; 8 | import net.minecraft.world.level.biome.Biome; 9 | import net.minecraft.world.level.biome.CheckerboardColumnBiomeSource; 10 | import net.minecraft.world.level.levelgen.WorldGenerationContext; 11 | import net.minecraft.world.level.levelgen.heightproviders.HeightProvider; 12 | import net.minecraft.world.level.levelgen.structure.Structure; 13 | 14 | public final class JigsawStructureBiomeCheck 15 | { 16 | public static boolean checkBiomes( 17 | StructureData structureData, 18 | HeightProvider startHeight, 19 | Structure.GenerationContext generationContext 20 | ) { 21 | var biomeCheckDistance = (int) Math.ceil(structureData.getBiomeCheckDistance() / 16.0); 22 | 23 | if (biomeCheckDistance == 0 || generationContext.biomeSource() instanceof CheckerboardColumnBiomeSource) { 24 | return true; 25 | } 26 | 27 | ChunkPos chunkPos = generationContext.chunkPos(); 28 | int y = startHeight.sample(generationContext.random(), new WorldGenerationContext(generationContext.chunkGenerator(), generationContext.heightAccessor())); 29 | var blockPos = new BlockPos(generationContext.chunkPos().getMinBlockX(), y, generationContext.chunkPos().getMinBlockZ()); 30 | 31 | int sectionY = QuartPos.fromBlock(blockPos.getY()); 32 | 33 | for (int curChunkX = chunkPos.x - biomeCheckDistance; curChunkX <= chunkPos.x + biomeCheckDistance; curChunkX++) { 34 | for (int curChunkZ = chunkPos.z - biomeCheckDistance; curChunkZ <= chunkPos.z + biomeCheckDistance; curChunkZ++) { 35 | Holder biome = generationContext.biomeSource().getNoiseBiome(QuartPos.fromSection(curChunkX), sectionY, QuartPos.fromSection(curChunkZ), generationContext.randomState().sampler()); 36 | if (!generationContext.validBiome().test(biome)) { 37 | return false; 38 | } 39 | } 40 | } 41 | 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/checks/JigsawStructureFlatnessCheck.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.checks; 2 | 3 | import com.faboslav.structurify.common.config.data.StructureData; 4 | import net.minecraft.core.BlockPos; 5 | import net.minecraft.world.level.ChunkPos; 6 | import net.minecraft.world.level.NoiseColumn; 7 | import net.minecraft.world.level.block.state.BlockState; 8 | import net.minecraft.world.level.levelgen.Heightmap; 9 | import net.minecraft.world.level.levelgen.WorldGenerationContext; 10 | import net.minecraft.world.level.levelgen.heightproviders.HeightProvider; 11 | import net.minecraft.world.level.levelgen.structure.Structure; 12 | 13 | public final class JigsawStructureFlatnessCheck 14 | { 15 | public static boolean checkFlatness( 16 | StructureData structureData, 17 | HeightProvider startHeight, 18 | Structure.GenerationContext generationContext 19 | ) { 20 | var flatnessCheckDistance = structureData.getFlatnessCheckDistance(); 21 | var offsetStep = (int) Math.ceil(flatnessCheckDistance / 2.0F); 22 | int stepAmount = (int) Math.pow((double) (2 * flatnessCheckDistance) / offsetStep + 1, 2); 23 | int allowedAirBlockSteps = stepAmount / 2; 24 | int allowedLiquidBlockSteps = stepAmount / 2; 25 | var flatnessCheckThreshold = structureData.getFlatnessCheckThreshold(); 26 | var areAirBlocksAllowed = structureData.areAirBlocksAllowedInFlatnessCheck(); 27 | var areLiquidBlocksAllowed = structureData.areLiquidBlocksAllowedInFlatnessCheck(); 28 | 29 | if (flatnessCheckDistance == 0 || flatnessCheckThreshold == 0) { 30 | return true; 31 | } 32 | 33 | ChunkPos chunkPos = generationContext.chunkPos(); 34 | int y = startHeight.sample(generationContext.random(), new WorldGenerationContext(generationContext.chunkGenerator(), generationContext.heightAccessor())); 35 | var blockPos = new BlockPos(chunkPos.getMinBlockX(), y, chunkPos.getMinBlockZ()); 36 | 37 | int baseX = blockPos.getX(); 38 | int baseZ = blockPos.getZ(); 39 | int minHeight = Integer.MAX_VALUE; 40 | int maxHeight = Integer.MIN_VALUE; 41 | 42 | int airBlockSteps = 0; 43 | int fluidBlockSteps = 0; 44 | 45 | for (int xOffset = -flatnessCheckDistance; xOffset <= flatnessCheckDistance; xOffset += offsetStep) { 46 | for (int zOffset = -flatnessCheckDistance; zOffset <= flatnessCheckDistance; zOffset += offsetStep) { 47 | int x = xOffset + baseX; 48 | int z = zOffset + baseZ; 49 | int height = generationContext.chunkGenerator().getFirstOccupiedHeight(x, z, Heightmap.Types.WORLD_SURFACE_WG, generationContext.heightAccessor(), generationContext.randomState()); 50 | 51 | minHeight = Math.min(minHeight, height); 52 | maxHeight = Math.max(maxHeight, height); 53 | 54 | if (maxHeight - minHeight > flatnessCheckThreshold) { 55 | return false; 56 | } 57 | 58 | if (!areAirBlocksAllowed || !areLiquidBlocksAllowed) { 59 | NoiseColumn blockView = generationContext.chunkGenerator().getBaseColumn( 60 | x, 61 | z, 62 | generationContext.heightAccessor(), 63 | generationContext.randomState() 64 | ); 65 | 66 | BlockState blockState = blockView.getBlock(height); 67 | 68 | // Structurify.getLogger().info("blockstate: " + blockState + " at: " + x + ", " + height + ", " + z); 69 | 70 | if (!areAirBlocksAllowed && blockState.isAir()) { 71 | airBlockSteps++; 72 | 73 | if (airBlockSteps >= allowedAirBlockSteps) { 74 | // Structurify.getLogger().info("air"); 75 | return false; 76 | } 77 | } 78 | 79 | if (!areLiquidBlocksAllowed && !blockState.getFluidState().isEmpty()) { 80 | fluidBlockSteps++; 81 | 82 | if (fluidBlockSteps >= allowedLiquidBlockSteps) { 83 | // Structurify.getLogger().info("liquid"); 84 | return false; 85 | } 86 | } 87 | } 88 | } 89 | } 90 | 91 | return true; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/checks/StructureDistanceFromWorldCenterCheck.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.checks; 2 | 3 | import net.minecraft.core.BlockPos; 4 | 5 | /** 6 | * Inspired by use in Repurposed Structures mod 7 | * 8 | * @author TelepathicGrunt 9 | * https://github.com/TelepathicGrunt/RepurposedStructures/blob/1.21-Arch/common/src/main/java/com/telepathicgrunt/repurposedstructures/world/placements/MinDistanceFromWorldOriginPlacement.java 10 | */ 11 | public final class StructureDistanceFromWorldCenterCheck 12 | { 13 | public static boolean checkStructureDistanceFromWorldCenter( 14 | BlockPos structureBlockPos, 15 | int minStructureDistanceFromWorldCenter 16 | ) { 17 | return structureBlockPos.distManhattan(BlockPos.ZERO) >= minStructureDistanceFromWorldCenter; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/commands/DumpCommand.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.commands; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.mojang.brigadier.CommandDispatcher; 5 | import net.minecraft.commands.CommandSourceStack; 6 | import net.minecraft.commands.Commands; 7 | import net.minecraft.network.chat.Component; 8 | 9 | public class DumpCommand 10 | { 11 | public static void createCommand(CommandDispatcher dispatcher) { 12 | dispatcher.register( 13 | Commands.literal("structurify") 14 | .requires(source -> source.hasPermission(2)) 15 | .then(Commands.literal("dump") 16 | .executes(context -> { 17 | Structurify.getConfig().dump(); 18 | context.getSource().sendSuccess( 19 | () -> Component.literal("Structurify config dumped to \"" + Structurify.getConfig().configDumpPath + "\"."), 20 | !context.getSource().isPlayer() 21 | ); 22 | return 1; 23 | }) 24 | ) 25 | ); 26 | } 27 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/config/StructurifyConfigLoader.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.config; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.events.common.LoadConfigEvent; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public final class StructurifyConfigLoader 10 | { 11 | public static void loadConfig(final LoadConfigEvent event) { 12 | if (Structurify.getConfig().isLoaded) { 13 | return; 14 | } 15 | 16 | Structurify.getConfig().load(); 17 | 18 | List disabledStructures = Structurify.getConfig().getStructureData().entrySet() 19 | .stream() 20 | .filter(entry -> entry.getValue().isDisabled()) 21 | .map(Map.Entry::getKey) 22 | .toList(); 23 | 24 | if (!disabledStructures.isEmpty()) { 25 | Structurify.getLogger().info("Disabled {} structures: {}", disabledStructures.size(), disabledStructures); 26 | } 27 | 28 | List changedStructureSets = Structurify.getConfig().getStructureSetData().entrySet() 29 | .stream() 30 | .filter(entry -> entry.getValue().isUsingDefaultValues()) 31 | .map(Map.Entry::getKey) 32 | .toList(); 33 | 34 | if (Structurify.getConfig().enableGlobalSpacingAndSeparationModifier && Structurify.getConfig().globalSpacingAndSeparationModifier != 1.0D) { 35 | Structurify.getLogger().info("Enabled global spacing and separation modifier with value of {}", Structurify.getConfig().globalSpacingAndSeparationModifier); 36 | } 37 | 38 | if (!changedStructureSets.isEmpty()) { 39 | Structurify.getLogger().info("Changed settings of {} structures sets: {}", changedStructureSets.size(), changedStructureSets); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/config/client/api/controller/BiomeStringController.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.config.client.api.controller; 2 | 3 | import com.faboslav.structurify.common.config.client.api.controller.element.BiomeStringControllerElement; 4 | import com.faboslav.structurify.common.config.data.WorldgenDataProvider; 5 | import com.faboslav.structurify.common.util.LanguageUtil; 6 | import dev.isxander.yacl3.api.Option; 7 | import dev.isxander.yacl3.api.utils.Dimension; 8 | import dev.isxander.yacl3.gui.AbstractWidget; 9 | import dev.isxander.yacl3.gui.YACLScreen; 10 | import dev.isxander.yacl3.gui.controllers.dropdown.AbstractDropdownController; 11 | import net.minecraft.network.chat.Component; 12 | 13 | import java.util.List; 14 | 15 | public final class BiomeStringController extends AbstractDropdownController 16 | { 17 | private final List allowedValues; 18 | 19 | public BiomeStringController(Option option) { 20 | super(option, WorldgenDataProvider.getBiomes(), false, false); 21 | this.allowedValues = WorldgenDataProvider.getBiomes(); 22 | } 23 | 24 | @Override 25 | public String getString() { 26 | return option.pendingValue(); 27 | } 28 | 29 | @Override 30 | public void setFromString(String value) { 31 | option.requestSet(value); 32 | } 33 | 34 | /* 35 | @Override 36 | public boolean isValueValid(String value) { 37 | if (!value.isBlank()) { 38 | var slugifiedValue = value.toLowerCase().replace(" ", "_"); 39 | 40 | for(var allowedValue : this.allowedValues) { 41 | var slugifiedBiome = allowedValue.toLowerCase().replace(" ", "_"); 42 | var slugifiedTranslatedBiome = LanguageUtil.translateId("biome", allowedValue).getString().toLowerCase().replace(" ", "_"); 43 | 44 | if( slugifiedBiome.contains(slugifiedValue) || slugifiedTranslatedBiome.contains(slugifiedValue)) { 45 | return true; 46 | } 47 | } 48 | } 49 | 50 | return super.isValueValid(value); 51 | }*/ 52 | 53 | @Override 54 | protected String getValidValue(String value) { 55 | return this.getValidValue(value, 0); 56 | } 57 | 58 | @Override 59 | protected String getValidValue(String value, int offset) { 60 | if (!value.isBlank()) { 61 | var slugifiedValue = value.toLowerCase().replace(" ", "_"); 62 | var validBiomes = this.allowedValues.stream().filter(biome -> { 63 | var slugifiedBiome = biome.toLowerCase().replace(" ", "_"); 64 | var slugifiedTranslatedBiome = LanguageUtil.translateId("biome", biome).getString().toLowerCase().replace(" ", "_"); 65 | return slugifiedBiome.contains(slugifiedValue) || slugifiedTranslatedBiome.contains(slugifiedValue); 66 | }).sorted((s1, s2) -> { 67 | 68 | if (s1.startsWith(slugifiedValue) && !s2.startsWith(slugifiedValue)) { 69 | return -1; 70 | } else { 71 | return !s1.startsWith(slugifiedValue) && s2.startsWith(slugifiedValue) ? 1:s1.compareTo(s2); 72 | } 73 | }); 74 | 75 | var validBiome = validBiomes.skip(offset).findFirst().orElse(null); 76 | 77 | if (validBiome != null) { 78 | return validBiome; 79 | } 80 | } 81 | 82 | return super.getValidValue(value, offset); 83 | } 84 | 85 | @Override 86 | public Component formatValue() { 87 | return LanguageUtil.translateId("biome", getString()); 88 | } 89 | 90 | @Override 91 | public AbstractWidget provideWidget(YACLScreen screen, Dimension widgetDimension) { 92 | return new BiomeStringControllerElement(this, screen, widgetDimension); 93 | } 94 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/config/client/api/controller/DualController.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.config.client.api.controller; 2 | 3 | import com.faboslav.structurify.common.config.client.api.controller.element.DualControllerElement; 4 | import com.faboslav.structurify.common.config.client.api.option.OptionPair; 5 | import dev.isxander.yacl3.api.Controller; 6 | import dev.isxander.yacl3.api.LabelOption; 7 | import dev.isxander.yacl3.api.Option; 8 | import dev.isxander.yacl3.api.utils.Dimension; 9 | import dev.isxander.yacl3.gui.AbstractWidget; 10 | import dev.isxander.yacl3.gui.TextScaledButtonWidget; 11 | import dev.isxander.yacl3.gui.YACLScreen; 12 | import net.minecraft.network.chat.Component; 13 | 14 | public class DualController, V extends Option> implements Controller> 15 | { 16 | public final LabelOption labelOption; 17 | public final OptionPair optionPair; 18 | 19 | public DualController( 20 | LabelOption labelOption, 21 | OptionPair controllerPair 22 | ) { 23 | this.labelOption = labelOption; 24 | this.optionPair = controllerPair; 25 | } 26 | 27 | @Override 28 | public Option> option() { 29 | return null; 30 | } 31 | 32 | @Override 33 | public Component formatValue() { 34 | return optionPair.getFirstOption().controller().formatValue().copy().append(" | ").append(optionPair.getSecondOption().controller().formatValue()); 35 | } 36 | 37 | @Override 38 | public AbstractWidget provideWidget(YACLScreen screen, Dimension widgetDimension) { 39 | Dimension firstWidgetDimension = widgetDimension.withWidth((int) ((double) widgetDimension.width() * 0.5)); 40 | Dimension secondWidgetDimension = widgetDimension.moved(firstWidgetDimension.width(), 0).withWidth((int) ((double) widgetDimension.width() - firstWidgetDimension.width())); 41 | 42 | AbstractWidget labelWidget = this.labelOption.controller().provideWidget(screen, firstWidgetDimension); 43 | AbstractWidget firstOptionWidget = this.optionPair.getFirstOption().controller().provideWidget(screen, firstWidgetDimension); 44 | AbstractWidget secondOptionWidget = this.optionPair.getSecondOption().controller().provideWidget(screen, secondWidgetDimension); 45 | TextScaledButtonWidget resetButtonWidget; 46 | 47 | widgetDimension = widgetDimension.expanded(0, firstOptionWidget.getDimension().height()); 48 | 49 | if (this.optionPair.getFirstOption().controller().option().canResetToDefault() && firstOptionWidget.canReset() && this.optionPair.getSecondOption().controller().option().canResetToDefault() && secondOptionWidget.canReset()) { 50 | firstOptionWidget.setDimension(firstOptionWidget.getDimension().expanded(-10, 0)); 51 | secondOptionWidget.setDimension(secondOptionWidget.getDimension().expanded(-10, 0)); 52 | 53 | resetButtonWidget = new TextScaledButtonWidget(screen, secondOptionWidget.getDimension().xLimit() - 10, 0, 20, 20, 2f, Component.literal("\u21BB"), button -> { 54 | this.optionPair.getFirstOption().requestSetDefault(); 55 | this.optionPair.getSecondOption().requestSetDefault(); 56 | }); 57 | this.optionPair.getFirstOption().addListener((opt, val) -> resetButtonWidget.active = !opt.isPendingValueDefault() && opt.available()); 58 | this.optionPair.getSecondOption().addListener((opt, val) -> resetButtonWidget.active = !opt.isPendingValueDefault() && opt.available()); 59 | resetButtonWidget.active = !this.optionPair.getFirstOption().isPendingValueDefault() && this.optionPair.getFirstOption().available() && !this.optionPair.getSecondOption().isPendingValueDefault() && this.optionPair.getSecondOption().available(); 60 | } else { 61 | resetButtonWidget = null; 62 | } 63 | 64 | return new DualControllerElement(widgetDimension, labelWidget, firstOptionWidget, secondOptionWidget, resetButtonWidget); 65 | } 66 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/config/client/api/controller/StructureButtonController.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.config.client.api.controller; 2 | 3 | import com.faboslav.structurify.common.StructurifyClient; 4 | import com.faboslav.structurify.common.config.client.gui.StructureConfigScreen; 5 | import dev.isxander.yacl3.api.Option; 6 | import dev.isxander.yacl3.api.utils.Dimension; 7 | import dev.isxander.yacl3.gui.AbstractWidget; 8 | import dev.isxander.yacl3.gui.TextScaledButtonWidget; 9 | import dev.isxander.yacl3.gui.YACLScreen; 10 | import dev.isxander.yacl3.gui.controllers.BooleanController; 11 | import net.minecraft.client.gui.GuiGraphics; 12 | import net.minecraft.network.chat.Component; 13 | 14 | import java.util.function.Function; 15 | 16 | public class StructureButtonController extends BooleanController 17 | { 18 | private final String structureId; 19 | 20 | 21 | public StructureButtonController( 22 | Option option, 23 | String structureId, 24 | Function valueFormatter, 25 | boolean coloured 26 | ) { 27 | super(option, valueFormatter, coloured); 28 | 29 | this.structureId = structureId; 30 | } 31 | 32 | @Override 33 | public AbstractWidget provideWidget(YACLScreen screen, Dimension widgetDimension) { 34 | return new BooleanWithButtonControllerElement(this, screen, widgetDimension, structureId); 35 | } 36 | 37 | public static class BooleanWithButtonControllerElement extends BooleanControllerElement 38 | { 39 | private final TextScaledButtonWidget configurationButton; 40 | 41 | public BooleanWithButtonControllerElement( 42 | BooleanController control, 43 | YACLScreen screen, 44 | Dimension dim, 45 | String structureId 46 | ) { 47 | super(control, screen, dim); 48 | 49 | this.setDimension(this.getDimension().expanded(-20, 0)); 50 | this.configurationButton = new TextScaledButtonWidget(screen, this.getDimension().xLimit(), -50, 20, 20, 1.0f, Component.literal("\u2699").withStyle(style -> style.withBold(true)), button -> { 51 | var configScreen = StructurifyClient.getConfigScreen(); 52 | 53 | if (configScreen == null) { 54 | return; 55 | } 56 | 57 | YACLScreen structureScreen; 58 | 59 | if (!configScreen.structureScreens.containsKey(structureId)) { 60 | structureScreen = StructureConfigScreen.create(screen, structureId); 61 | configScreen.structureScreens.put(structureId, structureScreen); 62 | } else { 63 | structureScreen = configScreen.structureScreens.get(structureId); 64 | } 65 | 66 | configScreen.saveScreenState(screen); 67 | this.client.setScreen(structureScreen); 68 | configScreen.loadScreenState(structureScreen); 69 | }); 70 | this.configurationButton.active = true; 71 | } 72 | 73 | @Override 74 | public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { 75 | this.configurationButton.setY(getDimension().y()); 76 | this.configurationButton.render(graphics, mouseX, mouseY, delta); 77 | super.render(graphics, mouseX, mouseY, delta); 78 | } 79 | 80 | @Override 81 | public void mouseMoved(double mouseX, double mouseY) { 82 | super.mouseMoved(mouseX, mouseY); 83 | this.configurationButton.mouseMoved(mouseX, mouseY); 84 | } 85 | 86 | @Override 87 | public boolean mouseClicked(double mouseX, double mouseY, int button) { 88 | return super.mouseClicked(mouseX, mouseY, button) || this.configurationButton.mouseClicked(mouseX, mouseY, button); 89 | } 90 | 91 | @Override 92 | public boolean mouseReleased(double mouseX, double mouseY, int button) { 93 | return super.mouseReleased(mouseX, mouseY, button) || this.configurationButton.mouseReleased(mouseX, mouseY, button); 94 | } 95 | 96 | @Override 97 | public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { 98 | return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY) || this.configurationButton.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); 99 | } 100 | 101 | /*? >=1.20.4 {*/ 102 | @Override 103 | public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { 104 | return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount) || this.configurationButton.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); 105 | } 106 | /*?}*/ 107 | } 108 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/config/client/api/controller/builder/BiomeStringControllerBuilder.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.config.client.api.controller.builder; 2 | 3 | import com.faboslav.structurify.common.config.client.api.controller.BiomeStringController; 4 | import dev.isxander.yacl3.api.Controller; 5 | import dev.isxander.yacl3.api.Option; 6 | import dev.isxander.yacl3.impl.controller.AbstractControllerBuilderImpl; 7 | 8 | public final class BiomeStringControllerBuilder extends AbstractControllerBuilderImpl 9 | { 10 | private BiomeStringControllerBuilder(Option option) { 11 | super(option); 12 | } 13 | 14 | @Override 15 | public Controller build() { 16 | return new BiomeStringController(option); 17 | } 18 | 19 | public static BiomeStringControllerBuilder create(Option option) { 20 | return new BiomeStringControllerBuilder(option); 21 | } 22 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/config/client/api/controller/builder/DualControllerBuilder.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.config.client.api.controller.builder; 2 | 3 | import com.faboslav.structurify.common.config.client.api.controller.DualController; 4 | import com.faboslav.structurify.common.config.client.api.option.OptionPair; 5 | import dev.isxander.yacl3.api.Controller; 6 | import dev.isxander.yacl3.api.LabelOption; 7 | import dev.isxander.yacl3.api.Option; 8 | import dev.isxander.yacl3.api.controller.ControllerBuilder; 9 | 10 | public class DualControllerBuilder, V extends Option> implements ControllerBuilder> 11 | { 12 | private final LabelOption labelOption; 13 | private final K firstOption; 14 | private final V secondOption; 15 | 16 | public DualControllerBuilder(LabelOption labelOption, K firstOption, V secondOption) { 17 | this.labelOption = labelOption; 18 | this.firstOption = firstOption; 19 | this.secondOption = secondOption; 20 | } 21 | 22 | @Override 23 | public Controller> build() { 24 | return new DualController<>(labelOption, new OptionPair<>(firstOption, secondOption)); 25 | } 26 | 27 | public static , V extends Option> DualControllerBuilder create( 28 | LabelOption labelOption, 29 | K firstOption, 30 | V secondOption 31 | ) { 32 | return new DualControllerBuilder<>(labelOption, firstOption, secondOption); 33 | } 34 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/config/client/api/controller/builder/StructureButtonControllerBuilder.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.config.client.api.controller.builder; 2 | 3 | import com.faboslav.structurify.common.config.client.api.controller.StructureButtonController; 4 | import dev.isxander.yacl3.api.Controller; 5 | import dev.isxander.yacl3.api.Option; 6 | import dev.isxander.yacl3.api.controller.ValueFormatter; 7 | import dev.isxander.yacl3.gui.controllers.BooleanController; 8 | import dev.isxander.yacl3.impl.controller.BooleanControllerBuilderImpl; 9 | import org.apache.commons.lang3.Validate; 10 | 11 | public class StructureButtonControllerBuilder extends BooleanControllerBuilderImpl 12 | { 13 | private final String structureId; 14 | private boolean coloured = false; 15 | private ValueFormatter formatter = BooleanController.ON_OFF_FORMATTER::apply; 16 | 17 | public StructureButtonControllerBuilder(Option option, String structureId) { 18 | super(option); 19 | 20 | this.structureId = structureId; 21 | } 22 | 23 | public StructureButtonControllerBuilder coloured(boolean coloured) { 24 | this.coloured = coloured; 25 | return this; 26 | } 27 | 28 | public StructureButtonControllerBuilder formatValue(ValueFormatter formatter) { 29 | Validate.notNull(formatter, "formatter cannot be null"); 30 | 31 | this.formatter = formatter; 32 | return this; 33 | } 34 | 35 | public StructureButtonControllerBuilder onOffFormatter() { 36 | this.formatter = BooleanController.ON_OFF_FORMATTER::apply; 37 | return this; 38 | } 39 | 40 | public StructureButtonControllerBuilder yesNoFormatter() { 41 | this.formatter = BooleanController.YES_NO_FORMATTER::apply; 42 | return this; 43 | } 44 | 45 | public StructureButtonControllerBuilder trueFalseFormatter() { 46 | this.formatter = BooleanController.TRUE_FALSE_FORMATTER::apply; 47 | return this; 48 | } 49 | 50 | @Override 51 | public Controller build() { 52 | return new StructureButtonController(option, this.structureId, this.formatter::format, this.coloured); 53 | } 54 | 55 | public static StructureButtonControllerBuilder create(Option option, String structureId) { 56 | return new StructureButtonControllerBuilder(option, structureId); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/config/client/api/option/OptionPair.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.config.client.api.option; 2 | 3 | import dev.isxander.yacl3.api.Option; 4 | 5 | public final class OptionPair, V extends Option> 6 | { 7 | private final K firstOption; 8 | private final V secondOption; 9 | 10 | public OptionPair(K firstOption, V secondOption) { 11 | this.firstOption = firstOption; 12 | this.secondOption = secondOption; 13 | } 14 | 15 | public K getFirstOption() { 16 | return firstOption; 17 | } 18 | 19 | public V getSecondOption() { 20 | return secondOption; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/config/client/gui/StructurifyConfigScreenState.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.config.client.gui; 2 | 3 | public record StructurifyConfigScreenState( 4 | String lastSearchText, 5 | double lastScrollAmount 6 | ) 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/config/data/StructureData.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.config.data; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | public class StructureData 8 | { 9 | public final static boolean IS_DISABLED_DEFAULT_VALUE = false; 10 | public final static boolean ENABLE_FLATNESS_CHECK_DEFAULT_VALUE = false; 11 | public final static int FLATNESS_CHECK_THRESHOLD_DEFAULT_VALUE = 10; 12 | public final static boolean ENABLE_BIOME_CHECK_DEFAULT_VALUE = false; 13 | public final static boolean ALLOW_AIR_BLOCKS_IN_FLATNESS_CHECK_DEFAULT_VALUE = false; 14 | public final static boolean ALLOW_LIQUID_BLOCKS_IN_FLATNESS_CHECK_DEFAULT_VALUE = false; 15 | 16 | private final List defaultBiomes; 17 | private final int defaultCheckDistance; 18 | 19 | private boolean isDisabled = IS_DISABLED_DEFAULT_VALUE; 20 | private boolean enableFlatnessCheck = ENABLE_FLATNESS_CHECK_DEFAULT_VALUE; 21 | private int flatnessCheckDistance; 22 | private int flatnessCheckThreshold = FLATNESS_CHECK_THRESHOLD_DEFAULT_VALUE; 23 | private boolean allowAirBlocksInFlatnessCheck = ALLOW_AIR_BLOCKS_IN_FLATNESS_CHECK_DEFAULT_VALUE; 24 | private boolean allowLiquidBlocksInFlatnessCheck = ALLOW_LIQUID_BLOCKS_IN_FLATNESS_CHECK_DEFAULT_VALUE; 25 | private boolean enableBiomeCheck = ENABLE_BIOME_CHECK_DEFAULT_VALUE; 26 | private int biomeCheckDistance; 27 | private List biomes; 28 | 29 | public StructureData(List biomes, int checkDistance) { 30 | this.defaultBiomes = biomes; 31 | this.biomes = biomes.stream().toList(); 32 | this.defaultCheckDistance = checkDistance; 33 | this.flatnessCheckDistance = checkDistance; 34 | this.biomeCheckDistance = checkDistance; 35 | } 36 | 37 | public boolean isUsingDefaultValues() { 38 | var biomes = new ArrayList<>(this.biomes); 39 | var defaultBiomes = new ArrayList<>(this.defaultBiomes); 40 | 41 | Collections.sort(biomes); 42 | Collections.sort(defaultBiomes); 43 | 44 | return this.isDisabled == IS_DISABLED_DEFAULT_VALUE 45 | && this.enableFlatnessCheck == ENABLE_FLATNESS_CHECK_DEFAULT_VALUE 46 | && this.flatnessCheckDistance == this.defaultCheckDistance 47 | && this.flatnessCheckThreshold == FLATNESS_CHECK_THRESHOLD_DEFAULT_VALUE 48 | && this.enableBiomeCheck == ENABLE_BIOME_CHECK_DEFAULT_VALUE 49 | && this.biomeCheckDistance == this.defaultCheckDistance 50 | && biomes.equals(defaultBiomes); 51 | } 52 | 53 | public boolean isDisabled() { 54 | return this.isDisabled; 55 | } 56 | 57 | public void setDisabled(boolean isDisabled) { 58 | this.isDisabled = isDisabled; 59 | } 60 | 61 | public int getDefaultCheckDistance() { 62 | return this.defaultCheckDistance; 63 | } 64 | 65 | public boolean isFlatnessCheckEnabled() { 66 | return this.enableFlatnessCheck; 67 | } 68 | 69 | public void setEnableFlatnessCheck(boolean enableFlatnessCheck) { 70 | this.enableFlatnessCheck = enableFlatnessCheck; 71 | } 72 | 73 | public boolean areAirBlocksAllowedInFlatnessCheck() { 74 | return this.allowAirBlocksInFlatnessCheck; 75 | } 76 | 77 | public void setAllowAirBlocksInFlatnessCheck(boolean allowAirBlocksInFlatnessCheck) { 78 | this.allowAirBlocksInFlatnessCheck = allowAirBlocksInFlatnessCheck; 79 | } 80 | 81 | public boolean areLiquidBlocksAllowedInFlatnessCheck() { 82 | return this.allowLiquidBlocksInFlatnessCheck; 83 | } 84 | 85 | public void setAllowLiquidBlocksInFlatnessCheck(boolean allowLiquidBlocksInFlatnessCheck) { 86 | this.allowLiquidBlocksInFlatnessCheck = allowLiquidBlocksInFlatnessCheck; 87 | } 88 | 89 | public int getFlatnessCheckDistance() { 90 | return this.flatnessCheckDistance; 91 | } 92 | 93 | public void setFlatnessCheckDistance(int flatnessCheckDistance) { 94 | this.flatnessCheckDistance = flatnessCheckDistance; 95 | } 96 | 97 | public int getFlatnessCheckThreshold() { 98 | return this.flatnessCheckThreshold; 99 | } 100 | 101 | public void setFlatnessCheckThreshold(int flatnessCheckThreshold) { 102 | this.flatnessCheckThreshold = flatnessCheckThreshold; 103 | } 104 | 105 | public boolean isBiomeCheckEnabled() { 106 | return this.enableBiomeCheck; 107 | } 108 | 109 | public void setEnableBiomeCheck(boolean enableBiomeCheck) { 110 | this.enableBiomeCheck = enableBiomeCheck; 111 | } 112 | 113 | public int getBiomeCheckDistance() { 114 | return this.biomeCheckDistance; 115 | } 116 | 117 | public void setBiomeCheckDistance(int biomeCheckDistance) { 118 | this.biomeCheckDistance = biomeCheckDistance; 119 | } 120 | 121 | public List getDefaultBiomes() { 122 | return this.defaultBiomes; 123 | } 124 | 125 | public List getBiomes() { 126 | return this.biomes; 127 | } 128 | 129 | public void setBiomes(List biomes) { 130 | this.biomes = biomes; 131 | } 132 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/config/data/StructureSetData.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.config.data; 2 | 3 | public final class StructureSetData 4 | { 5 | public static final boolean OVERRIDE_GLOBAL_SPACING_AND_SEPARATION_MODIFIER_DEFAULT_VALUE = false; 6 | public static final int MIN_SALT = 1; 7 | public static final int MAX_SALT = Integer.MAX_VALUE; 8 | public static final float MIN_FREQUENCY = 0.0F; 9 | public static final float MAX_FREQUENCY = 1.0F; 10 | public static final int MAX_SPACING = 4096; 11 | public static final int MAX_SEPARATION = 4096; 12 | 13 | private boolean overrideGlobalSpacingAndSeparationModifier = OVERRIDE_GLOBAL_SPACING_AND_SEPARATION_MODIFIER_DEFAULT_VALUE; 14 | private final int defaultSalt; 15 | private final float defaultFrequency; 16 | private final int defaultSpacing; 17 | private final int defaultSeparation; 18 | private int salt; 19 | private float frequency; 20 | private int spacing; 21 | private int separation; 22 | 23 | public StructureSetData(int salt, float frequency, int spacing, int separation) { 24 | this.defaultSalt = salt; 25 | this.defaultFrequency = frequency; 26 | this.defaultSpacing = spacing; 27 | this.defaultSeparation = separation; 28 | this.salt = salt; 29 | this.frequency = frequency; 30 | this.spacing = spacing; 31 | this.separation = separation; 32 | } 33 | 34 | public boolean isUsingDefaultValues() { 35 | return this.overrideGlobalSpacingAndSeparationModifier != OVERRIDE_GLOBAL_SPACING_AND_SEPARATION_MODIFIER_DEFAULT_VALUE 36 | || this.salt != defaultSalt 37 | || this.frequency != defaultFrequency 38 | || this.spacing != defaultSpacing 39 | || this.separation != this.defaultSeparation; 40 | } 41 | 42 | public boolean overrideGlobalSpacingAndSeparationModifier() { 43 | return this.overrideGlobalSpacingAndSeparationModifier; 44 | } 45 | 46 | public void setOverrideGlobalSpacingAndSeparationModifier(boolean overrideGlobalSpacingAndSeparationModifier) { 47 | this.overrideGlobalSpacingAndSeparationModifier = overrideGlobalSpacingAndSeparationModifier; 48 | } 49 | 50 | public int getDefaultSalt() { 51 | return this.defaultSalt; 52 | } 53 | 54 | public float getDefaultFrequency() { 55 | return this.defaultFrequency; 56 | } 57 | 58 | public int getDefaultSpacing() { 59 | return this.defaultSpacing; 60 | } 61 | 62 | public int getDefaultSeparation() { 63 | return this.defaultSeparation; 64 | } 65 | 66 | public int getSalt() { 67 | return this.salt; 68 | } 69 | 70 | public void setSalt(int salt) { 71 | this.salt = salt; 72 | } 73 | 74 | public float getFrequency() { 75 | return this.frequency; 76 | } 77 | 78 | public void setFrequency(float frequency) { 79 | this.frequency = frequency; 80 | } 81 | 82 | public int getSpacing() { 83 | return this.spacing; 84 | } 85 | 86 | public void setSpacing(int spacing) { 87 | this.spacing = spacing; 88 | } 89 | 90 | public int getSeparation() { 91 | return this.separation; 92 | } 93 | 94 | public void setSeparation(int separation) { 95 | this.separation = separation; 96 | } 97 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/events/base/CancellableEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.events.base; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.function.Consumer; 6 | 7 | /** 8 | * Event related is code based on The Bumblezone/Resourceful Lib mods with permissions from the authors 9 | * 10 | * @author TelepathicGrunt 11 | * https://github.com/TelepathicGrunt/Bumblezone 12 | * @author ThatGravyBoat 13 | * https://github.com/Team-Resourceful/ResourcefulLib 14 | */ 15 | public final class CancellableEventHandler 16 | { 17 | private final List> listeners = new ArrayList<>(); 18 | 19 | public CancellableEventHandler() { 20 | 21 | } 22 | 23 | public void addListener(CancellableFunction listener) { 24 | listeners.add(listener); 25 | } 26 | 27 | public void addListener(CancellableFunctionNoReturn listener) { 28 | addListener((b, t) -> { 29 | listener.apply(b, t); 30 | return false; 31 | }); 32 | } 33 | 34 | public void addListener(CancellableFunctionOnlyReturn listener) { 35 | addListener((b, t) -> { 36 | return listener.apply(t); 37 | }); 38 | } 39 | 40 | public void addListener(Consumer listener) { 41 | addListener((t) -> { 42 | listener.accept(t); 43 | return false; 44 | }); 45 | } 46 | 47 | public void removeListener(CancellableFunction listener) { 48 | listeners.remove(listener); 49 | } 50 | 51 | public boolean invoke(T event, boolean isCancelled) { 52 | for (CancellableFunction listener : listeners) { 53 | if (listener.apply(isCancelled, event)) { 54 | isCancelled = true; 55 | } 56 | } 57 | return isCancelled; 58 | } 59 | 60 | public boolean invoke(T event) { 61 | return invoke(event, false); 62 | } 63 | 64 | @FunctionalInterface 65 | public interface CancellableFunction 66 | { 67 | 68 | boolean apply(boolean cancelled, T event); 69 | } 70 | 71 | @FunctionalInterface 72 | public interface CancellableFunctionNoReturn 73 | { 74 | 75 | void apply(boolean cancelled, T event); 76 | } 77 | 78 | @FunctionalInterface 79 | public interface CancellableFunctionOnlyReturn 80 | { 81 | 82 | boolean apply(T event); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/events/base/EventHandler.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.events.base; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.function.Consumer; 6 | 7 | /** 8 | * Event related is code based on The Bumblezone/Resourceful Lib mods with permissions from the authors 9 | * 10 | * @author TelepathicGrunt 11 | * https://github.com/TelepathicGrunt/Bumblezone 12 | * @author ThatGravyBoat 13 | * https://github.com/Team-Resourceful/ResourcefulLib 14 | */ 15 | public final class EventHandler 16 | { 17 | private final List> listeners = new ArrayList<>(); 18 | 19 | public EventHandler() { 20 | 21 | } 22 | 23 | public void addListener(Consumer listener) { 24 | listeners.add(listener); 25 | } 26 | 27 | public void removeListener(Consumer listener) { 28 | listeners.remove(listener); 29 | } 30 | 31 | public void invoke(T event) { 32 | for (Consumer listener : listeners) { 33 | listener.accept(event); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/events/common/LoadConfigEvent.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.events.common; 2 | 3 | import com.faboslav.structurify.common.events.base.EventHandler; 4 | 5 | public record LoadConfigEvent() 6 | { 7 | public static final EventHandler EVENT = new EventHandler<>(); 8 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/events/common/UpdateRegistriesEvent.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.events.common; 2 | 3 | import com.faboslav.structurify.common.events.base.EventHandler; 4 | import net.minecraft.core.HolderLookup; 5 | 6 | public record UpdateRegistriesEvent(HolderLookup.Provider registryManager) 7 | { 8 | public static final EventHandler EVENT = new EventHandler<>(); 9 | } 10 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/AbstractWidgetInvoker.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin; 2 | 3 | import net.minecraft.client.gui.components.AbstractWidget; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | 6 | //? <1.21 { 7 | /*import org.spongepowered.asm.mixin.gen.Accessor; 8 | *///?} 9 | 10 | @Mixin(AbstractWidget.class) 11 | public interface AbstractWidgetInvoker 12 | { 13 | //? <1.21 { 14 | /*@Accessor("height") 15 | void setHeight(int height); 16 | *///?} 17 | } 18 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/ChunkGeneratorMixin.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.checks.StructureDistanceFromWorldCenterCheck; 5 | import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; 6 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation; 7 | import net.minecraft.core.RegistryAccess; 8 | import net.minecraft.core.SectionPos; 9 | import net.minecraft.world.level.ChunkPos; 10 | import net.minecraft.world.level.StructureManager; 11 | import net.minecraft.world.level.chunk.ChunkAccess; 12 | import net.minecraft.world.level.chunk.ChunkGenerator; 13 | import net.minecraft.world.level.levelgen.RandomState; 14 | import net.minecraft.world.level.levelgen.structure.StructureSet; 15 | import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; 16 | import org.spongepowered.asm.mixin.Mixin; 17 | 18 | //? >=1.21.4 { 19 | import net.minecraft.resources.ResourceKey; 20 | import net.minecraft.world.level.Level; 21 | //?} 22 | 23 | @Mixin(ChunkGenerator.class) 24 | public final class ChunkGeneratorMixin 25 | { 26 | @WrapMethod( 27 | method = "tryGenerateStructure" 28 | ) 29 | public boolean structurify$trySetStructureStart( 30 | //? >=1.21.4 { 31 | StructureSet.StructureSelectionEntry structureSelectionEntry, 32 | StructureManager structureManager, 33 | RegistryAccess registryAccess, 34 | RandomState randomState, 35 | StructureTemplateManager structureTemplateManager, 36 | long seed, 37 | ChunkAccess chunkAccess, 38 | ChunkPos chunkPos, 39 | SectionPos sectionPos, 40 | ResourceKey resourceKey, 41 | Operation original 42 | //?} else { 43 | /*StructureSet.StructureSelectionEntry structureSelectionEntry, 44 | StructureManager structureManager, 45 | RegistryAccess registryAccess, 46 | RandomState randomState, 47 | StructureTemplateManager structureTemplateManager, 48 | long seed, 49 | ChunkAccess chunkAccess, 50 | ChunkPos chunkPos, 51 | SectionPos sectionPos, 52 | Operation original 53 | *///?} 54 | ) { 55 | if (Structurify.getConfig().disableAllStructures) { 56 | return false; 57 | } 58 | 59 | var minStructureDistanceFromWorldCenter = Structurify.getConfig().minStructureDistanceFromWorldCenter; 60 | 61 | if (minStructureDistanceFromWorldCenter > 0) { 62 | var checkStructureDistanceFromWorldCenterResult = StructureDistanceFromWorldCenterCheck.checkStructureDistanceFromWorldCenter(chunkPos.getWorldPosition(), minStructureDistanceFromWorldCenter); 63 | 64 | if (!checkStructureDistanceFromWorldCenterResult) { 65 | return false; 66 | } 67 | } 68 | 69 | String structureName = structureSelectionEntry.structure().unwrapKey().get().location().toString(); 70 | var structureData = Structurify.getConfig().getStructureData().getOrDefault(structureName, null); 71 | 72 | if (structureData != null && structureData.isDisabled()) { 73 | return false; 74 | } 75 | 76 | //? >=1.21.4 { 77 | return original.call(structureSelectionEntry, structureManager, registryAccess, randomState, structureTemplateManager, seed, chunkAccess, chunkPos, sectionPos, resourceKey); 78 | //?} else { 79 | /*return original.call(structureSelectionEntry, structureManager, registryAccess, randomState, structureTemplateManager, seed, chunkAccess, chunkPos, sectionPos); 80 | *///?} 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/LocateCommandMixin.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.config.data.StructureData; 5 | import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; 6 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation; 7 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 8 | import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; 9 | import net.minecraft.commands.CommandSourceStack; 10 | import net.minecraft.commands.arguments.ResourceOrTagKeyArgument; 11 | import net.minecraft.core.registries.Registries; 12 | import net.minecraft.network.chat.Component; 13 | import net.minecraft.resources.ResourceKey; 14 | import net.minecraft.server.commands.LocateCommand; 15 | import net.minecraft.tags.TagKey; 16 | import net.minecraft.world.level.levelgen.structure.Structure; 17 | import org.spongepowered.asm.mixin.Mixin; 18 | import org.spongepowered.asm.mixin.Unique; 19 | 20 | import java.util.Optional; 21 | 22 | @Mixin(LocateCommand.class) 23 | public class LocateCommandMixin 24 | { 25 | @WrapMethod( 26 | method = "locateStructure" 27 | ) 28 | private static int structurify$executeLocateStructure( 29 | CommandSourceStack source, 30 | ResourceOrTagKeyArgument.Result predicate, 31 | Operation original 32 | ) throws CommandSyntaxException { 33 | if (Structurify.getConfig().disableAllStructures) { 34 | throw new SimpleCommandExceptionType(Component.translatable("command.structurify.locate.exception.all_structures_are_disabled")).create(); 35 | } 36 | 37 | // TODO handle the custom checks here? 38 | 39 | Optional> structureRegistryKey = predicate.unwrap().left(); 40 | Optional> structureTagKey = predicate.unwrap().right(); 41 | 42 | if (structureRegistryKey.isPresent()) { 43 | String structureId = structureRegistryKey.get().location().toString(); 44 | 45 | if (structurify$isStructureDisabled(structureId)) { 46 | throw new SimpleCommandExceptionType(Component.translatable("command.structurify.locate.structure_is_disabled", structureId)).create(); 47 | } 48 | } else if (structureTagKey.isPresent()) { 49 | try { 50 | source.getLevel().registryAccess().lookupOrThrow(Registries.STRUCTURE).get(structureTagKey.get()).ifPresent(tagStructures -> { 51 | boolean areAllStructuresInTagDisabled = true; 52 | 53 | for (var tagStructure : tagStructures) { 54 | String tagStructureId = tagStructure.unwrapKey().get().location().toString(); 55 | 56 | if (!structurify$isStructureDisabled(tagStructureId)) { 57 | areAllStructuresInTagDisabled = false; 58 | } 59 | } 60 | 61 | if (areAllStructuresInTagDisabled) { 62 | throw new RuntimeException(new SimpleCommandExceptionType(Component.translatable("command.structurify.locate.structure_is_disabled", "#" + structureTagKey.get().location().toString())).create()); 63 | } 64 | }); 65 | } catch (RuntimeException e) { 66 | if (e.getCause() instanceof CommandSyntaxException) { 67 | throw (CommandSyntaxException) e.getCause(); 68 | } else { 69 | throw e; 70 | } 71 | } 72 | } 73 | 74 | return original.call(source, predicate); 75 | } 76 | 77 | @Unique 78 | private static boolean structurify$isStructureDisabled(String structureId) { 79 | StructureData structureData = Structurify.getConfig().getStructureData().getOrDefault(structureId, null); 80 | 81 | if (structureData == null) { 82 | return false; 83 | } 84 | 85 | return structureData.isDisabled(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/ResourcePackManagerAccessor.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin; 2 | 3 | import net.minecraft.server.packs.repository.PackRepository; 4 | import net.minecraft.server.packs.repository.RepositorySource; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.gen.Accessor; 7 | 8 | import java.util.Set; 9 | 10 | @Mixin(PackRepository.class) 11 | public interface ResourcePackManagerAccessor 12 | { 13 | @Accessor 14 | Set getSources(); 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/WorldOpenFlowsMixin.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin; 2 | 3 | import com.mojang.serialization.Lifecycle; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.gui.screens.worldselection.CreateWorldScreen; 6 | import net.minecraft.client.gui.screens.worldselection.WorldOpenFlows; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Inject; 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 11 | 12 | @Mixin(WorldOpenFlows.class) 13 | public abstract class WorldOpenFlowsMixin 14 | { 15 | @Inject( 16 | method = "confirmWorldCreation", 17 | at = @At("HEAD"), 18 | cancellable = true 19 | ) 20 | private static void alwaysTreatAsStable( 21 | Minecraft client, 22 | CreateWorldScreen parent, 23 | Lifecycle lifecycle, 24 | Runnable loader, 25 | boolean bypassWarnings, 26 | CallbackInfo ci 27 | ) { 28 | if (lifecycle != Lifecycle.stable()) { 29 | loader.run(); 30 | ci.cancel(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/compat/RepurposedStructuresModifySpreadMixin.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin.compat; 2 | 3 | import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadStructurePlacement; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | 6 | //? repurposed_structures { 7 | import com.faboslav.structurify.common.api.StructurifyRandomSpreadStructurePlacement; 8 | import com.faboslav.structurify.common.util.RandomSpreadUtil; 9 | import com.llamalad7.mixinextras.injector.ModifyExpressionValue; 10 | import com.llamalad7.mixinextras.injector.ModifyReturnValue; 11 | import com.telepathicgrunt.repurposedstructures.world.structures.placements.AdvancedRandomSpread; 12 | import net.minecraft.core.Vec3i; 13 | import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadType; 14 | import org.objectweb.asm.Opcodes; 15 | import org.spongepowered.asm.mixin.Final; 16 | import org.spongepowered.asm.mixin.Shadow; 17 | import org.spongepowered.asm.mixin.injection.At; 18 | 19 | import java.util.Optional; 20 | 21 | @Mixin(value = AdvancedRandomSpread.class) 22 | public abstract class RepurposedStructuresModifySpreadMixin extends RandomSpreadStructurePlacement implements StructurifyRandomSpreadStructurePlacement 23 | { 24 | public RepurposedStructuresModifySpreadMixin( 25 | Vec3i vec3i, 26 | FrequencyReductionMethod frequencyReductionMethod, 27 | float f, 28 | int i, 29 | Optional optional, 30 | int j, 31 | int k, 32 | RandomSpreadType randomSpreadType 33 | ) { 34 | super(vec3i, frequencyReductionMethod, f, i, optional, j, k, randomSpreadType); 35 | } 36 | 37 | @Shadow 38 | @Final 39 | public abstract int spacing(); 40 | 41 | @ModifyReturnValue( 42 | method = "spacing", 43 | at = @At("RETURN"), 44 | require = 0 45 | ) 46 | protected int structurify$getSpacing(int originalSpacing) { 47 | return RandomSpreadUtil.getModifiedSpacing(this.structurify$getStructureSetIdentifier(), originalSpacing); 48 | } 49 | 50 | @ModifyReturnValue( 51 | method = "separation", 52 | at = @At("RETURN"), 53 | require = 0 54 | ) 55 | protected int structurify$getSeparation(int originalSeparation) { 56 | return RandomSpreadUtil.getModifiedSeparation(this.structurify$getStructureSetIdentifier(), this.spacing(), originalSeparation); 57 | } 58 | 59 | @ModifyExpressionValue( 60 | method = "getPotentialStructureChunk", 61 | at = @At( 62 | value = "FIELD", 63 | target = "Lcom/telepathicgrunt/repurposedstructures/world/structures/placements/AdvancedRandomSpread;spacing:I", 64 | opcode = Opcodes.GETFIELD 65 | ), 66 | require = 0 67 | ) 68 | protected int structurify$getStartChunkGetSpacing(int originalSpacing) { 69 | return RandomSpreadUtil.getModifiedSpacing(this.structurify$getStructureSetIdentifier(), originalSpacing); 70 | } 71 | 72 | @ModifyExpressionValue( 73 | method = "getPotentialStructureChunk", 74 | at = @At( 75 | value = "FIELD", 76 | target = "Lcom/telepathicgrunt/repurposedstructures/world/structures/placements/AdvancedRandomSpread;separation:I", 77 | opcode = Opcodes.GETFIELD 78 | ), 79 | require = 0 80 | ) 81 | protected int structurify$getStartChunkGetSeparation(int originalSeparation) { 82 | return RandomSpreadUtil.getModifiedSeparation(this.structurify$getStructureSetIdentifier(), this.spacing(), originalSeparation); 83 | } 84 | } 85 | //?} else { 86 | /*// This is just a placeholder mixin 87 | @Mixin(RandomSpreadStructurePlacement.class) 88 | public abstract class RepurposedStructuresModifySpreadMixin 89 | { 90 | } 91 | *///?} -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/plugin/StructurifyMixinPlugin.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin.plugin; 2 | 3 | import org.objectweb.asm.tree.ClassNode; 4 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 5 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | public class StructurifyMixinPlugin implements IMixinConfigPlugin 11 | { 12 | @Override 13 | public void onLoad(String mixinPackage) { 14 | } 15 | 16 | @Override 17 | public String getRefMapperConfig() { 18 | return null; 19 | } 20 | 21 | @Override 22 | public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { 23 | if (mixinClassName.equals("com.faboslav.structurify.common.mixin.WorldOpenFlowsMixin")) { 24 | return this.isClassAvailable("me.earth.mc_runtime_test.McRuntimeTest"); 25 | } 26 | 27 | if (mixinClassName.equals("com.faboslav.structurify.common.mixin.compat.RepurposedStructuresModifySpreadMixin")) { 28 | return this.isClassAvailable("com.telepathicgrunt.repurposedstructures.world.structures.placements.AdvancedRandomSpread"); 29 | } 30 | 31 | if (mixinClassName.equals("com.faboslav.structurify.forge.mixin.compat.StructureGelApiModifySpreadMixin")) { 32 | return this.isClassAvailable("com.legacy.structure_gel.api.structure.GridStructurePlacement"); 33 | } 34 | 35 | return true; 36 | } 37 | 38 | @Override 39 | public void acceptTargets(Set myTargets, Set otherTargets) { 40 | } 41 | 42 | @Override 43 | public List getMixins() { 44 | return null; 45 | } 46 | 47 | @Override 48 | public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { 49 | } 50 | 51 | @Override 52 | public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { 53 | } 54 | 55 | private boolean isClassAvailable(String className) { 56 | String classPath = className.replace('.', '/') + ".class"; 57 | return getClass().getClassLoader().getResource(classPath) != null; 58 | } 59 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/structure/StructureMixin.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin.structure; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.api.StructurifyStructure; 5 | import com.faboslav.structurify.common.modcompat.ModChecker; 6 | import com.faboslav.structurify.common.modcompat.ModCompat; 7 | import com.faboslav.structurify.common.registry.StructurifyRegistryManagerProvider; 8 | import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; 9 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation; 10 | import net.minecraft.core.Holder; 11 | import net.minecraft.core.HolderSet; 12 | import net.minecraft.core.registries.Registries; 13 | import net.minecraft.resources.ResourceKey; 14 | import net.minecraft.resources.ResourceLocation; 15 | import net.minecraft.tags.TagKey; 16 | import net.minecraft.world.level.biome.Biome; 17 | import net.minecraft.world.level.levelgen.structure.Structure; 18 | import org.jetbrains.annotations.Nullable; 19 | import org.spongepowered.asm.mixin.Mixin; 20 | import org.spongepowered.asm.mixin.Unique; 21 | 22 | import java.util.ArrayList; 23 | 24 | @Mixin(Structure.class) 25 | public abstract class StructureMixin implements StructurifyStructure 26 | { 27 | @Unique 28 | @Nullable 29 | public ResourceLocation structurify$structureIdentifier = null; 30 | 31 | public void structurify$setStructureIdentifier(ResourceLocation structureSetIdentifier) { 32 | this.structurify$structureIdentifier = structureSetIdentifier; 33 | } 34 | 35 | @Nullable 36 | public ResourceLocation structurify$getStructureIdentifier() { 37 | return this.structurify$structureIdentifier; 38 | } 39 | 40 | @Unique 41 | @Nullable 42 | public HolderSet structurify$structureBiomes = null; 43 | 44 | public void structurify$setStructureBiomes(@Nullable HolderSet biomeHolderSet) { 45 | this.structurify$structureBiomes = biomeHolderSet; 46 | } 47 | 48 | @Nullable 49 | public HolderSet structurify$getStructureBiomes() { 50 | return this.structurify$structureBiomes; 51 | } 52 | 53 | @WrapMethod( 54 | method = "biomes" 55 | ) 56 | private HolderSet structurify$biomes( 57 | Operation> original 58 | ) { 59 | if (this.structurify$getStructureBiomes() == null) { 60 | var biomeHolderSet = this.structurify$getBiomeHolderSet(original); 61 | this.structurify$setStructureBiomes(biomeHolderSet); 62 | } 63 | 64 | return this.structurify$getStructureBiomes(); 65 | } 66 | 67 | @Unique 68 | private HolderSet structurify$getBiomeHolderSet( 69 | Operation> original 70 | ) { 71 | ResourceLocation structureId = structurify$getStructureIdentifier(); 72 | 73 | if ( 74 | structureId == null 75 | || !Structurify.getConfig().getStructureData().containsKey(structureId.toString()) 76 | ) { 77 | return original.call(); 78 | } 79 | 80 | var biomeRegistry = StructurifyRegistryManagerProvider.getBiomeRegistry(); 81 | 82 | if (biomeRegistry == null) { 83 | return original.call(); 84 | } 85 | 86 | var structureData = Structurify.getConfig().getStructureData().get(structureId.toString()); 87 | var biomeIds = structureData.getBiomes(); 88 | 89 | for (ModCompat modCompat : ModChecker.BIOME_REPLACER_COMPATS) { 90 | biomeIds = modCompat.getReplacedBiomes(biomeIds); 91 | } 92 | 93 | ArrayList> biomeHolders = new ArrayList<>(); 94 | 95 | for (var biomeId : biomeIds) { 96 | if (biomeId.contains("#")) { 97 | var biomeTagKey = TagKey.create(Registries.BIOME, Structurify.makeNamespacedId(biomeId.replace("#", ""))); 98 | var biomeTagHolder = biomeRegistry.get(biomeTagKey).orElse(null); 99 | 100 | if (biomeTagHolder == null) { 101 | continue; 102 | } 103 | 104 | for (var biomeHolder : biomeTagHolder.stream().toList()) { 105 | biomeHolders.add(biomeHolder); 106 | } 107 | } else { 108 | var biomeResourceKey = ResourceKey.create(Registries.BIOME, Structurify.makeNamespacedId(biomeId.replace("#", ""))); 109 | var biomeHolder = biomeRegistry.get(biomeResourceKey).orElse(null); 110 | 111 | if (biomeHolder == null) { 112 | continue; 113 | } 114 | 115 | biomeHolders.add(biomeHolder); 116 | } 117 | } 118 | 119 | return HolderSet.direct(biomeHolders); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/structure/jigsaw/JigsawStructureMixin.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin.structure.jigsaw; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.checks.JigsawStructureBiomeCheck; 5 | import com.faboslav.structurify.common.checks.JigsawStructureFlatnessCheck; 6 | import com.faboslav.structurify.common.mixin.structure.StructureMixin; 7 | import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; 8 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation; 9 | import net.minecraft.resources.ResourceLocation; 10 | import net.minecraft.world.level.levelgen.heightproviders.HeightProvider; 11 | import net.minecraft.world.level.levelgen.structure.Structure.GenerationContext; 12 | import net.minecraft.world.level.levelgen.structure.Structure.GenerationStub; 13 | import net.minecraft.world.level.levelgen.structure.structures.JigsawStructure; 14 | import org.spongepowered.asm.mixin.Final; 15 | import org.spongepowered.asm.mixin.Mixin; 16 | import org.spongepowered.asm.mixin.Shadow; 17 | 18 | import java.util.Optional; 19 | 20 | @Mixin(JigsawStructure.class) 21 | public abstract class JigsawStructureMixin extends StructureMixin 22 | { 23 | @Shadow 24 | @Final 25 | private HeightProvider startHeight; 26 | 27 | @WrapMethod( 28 | method = "findGenerationPoint" 29 | ) 30 | private Optional structurify$getStructurePosition( 31 | GenerationContext generationContext, 32 | Operation> original 33 | ) { 34 | ResourceLocation structureId = structurify$getStructureIdentifier(); 35 | 36 | if ( 37 | structureId == null 38 | || !Structurify.getConfig().getStructureData().containsKey(structureId.toString()) 39 | ) { 40 | return original.call(generationContext); 41 | } 42 | 43 | var structureData = Structurify.getConfig().getStructureData().get(structureId.toString()); 44 | 45 | if (structureData.isFlatnessCheckEnabled()) { 46 | var flatnessCheckResult = JigsawStructureFlatnessCheck.checkFlatness(structureData, this.startHeight, generationContext); 47 | 48 | if (!flatnessCheckResult) { 49 | return Optional.empty(); 50 | } 51 | } 52 | 53 | if (structureData.isBiomeCheckEnabled()) { 54 | var biomeCheckResult = JigsawStructureBiomeCheck.checkBiomes(structureData, this.startHeight, generationContext); 55 | 56 | if (!biomeCheckResult) { 57 | return Optional.empty(); 58 | } 59 | } 60 | 61 | return original.call(generationContext); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/structure/jigsaw/MaxDistanceFromCenterAccessor.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin.structure.jigsaw; 2 | 3 | import net.minecraft.world.level.levelgen.structure.structures.JigsawStructure; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.gen.Accessor; 6 | 7 | @Mixin(JigsawStructure.class) 8 | public interface MaxDistanceFromCenterAccessor 9 | { 10 | @Accessor("maxDistanceFromCenter") 11 | int structurify$getMaxDistanceFromCenter(); 12 | } 13 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/structure/placement/RandomSpreadStructurePlacementMixin.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin.structure.placement; 2 | 3 | import com.faboslav.structurify.common.api.StructurifyRandomSpreadStructurePlacement; 4 | import com.faboslav.structurify.common.util.RandomSpreadUtil; 5 | import com.llamalad7.mixinextras.injector.ModifyExpressionValue; 6 | import com.llamalad7.mixinextras.injector.ModifyReturnValue; 7 | import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadStructurePlacement; 8 | import org.objectweb.asm.Opcodes; 9 | import org.spongepowered.asm.mixin.Final; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | 14 | @Mixin(RandomSpreadStructurePlacement.class) 15 | public abstract class RandomSpreadStructurePlacementMixin extends StructurePlacementMixin implements StructurifyRandomSpreadStructurePlacement 16 | { 17 | @Shadow 18 | @Final 19 | private int spacing; 20 | 21 | @Shadow 22 | @Final 23 | private int separation; 24 | 25 | @Shadow 26 | public abstract int spacing(); 27 | 28 | public int structurify$getOriginalSpacing() { 29 | return this.spacing; 30 | } 31 | 32 | public int structurify$getOriginalSeparation() { 33 | return this.separation; 34 | } 35 | 36 | @ModifyReturnValue( 37 | method = "spacing", 38 | at = @At("RETURN") 39 | ) 40 | protected int structurify$getSpacing(int originalSpacing) { 41 | return RandomSpreadUtil.getModifiedSpacing(this.structurify$getStructureSetIdentifier(), originalSpacing); 42 | } 43 | 44 | @ModifyReturnValue( 45 | method = "separation", 46 | at = @At("RETURN") 47 | ) 48 | protected int structurify$getSeparation(int originalSeparation) { 49 | return RandomSpreadUtil.getModifiedSeparation(this.structurify$getStructureSetIdentifier(), this.spacing(), originalSeparation); 50 | } 51 | 52 | @ModifyExpressionValue( 53 | method = "getPotentialStructureChunk", 54 | at = @At( 55 | value = "FIELD", 56 | target = "Lnet/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement;spacing:I", 57 | opcode = Opcodes.GETFIELD 58 | ) 59 | ) 60 | protected int structurify$getStartChunkGetSpacing(int originalSpacing) { 61 | return RandomSpreadUtil.getModifiedSpacing(this.structurify$getStructureSetIdentifier(), originalSpacing); 62 | } 63 | 64 | @ModifyExpressionValue( 65 | method = "getPotentialStructureChunk", 66 | at = @At( 67 | value = "FIELD", 68 | target = "Lnet/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement;separation:I", 69 | opcode = Opcodes.GETFIELD 70 | ) 71 | ) 72 | protected int structurify$getStartChunkGetSeparation(int originalSeparation) { 73 | return RandomSpreadUtil.getModifiedSeparation(this.structurify$getStructureSetIdentifier(), this.spacing(), originalSeparation); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/structure/placement/StructurePlacementMixin.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin.structure.placement; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.api.StructurifyStructurePlacement; 5 | import com.faboslav.structurify.common.util.RandomSpreadUtil; 6 | import com.llamalad7.mixinextras.injector.ModifyExpressionValue; 7 | import com.llamalad7.mixinextras.injector.ModifyReturnValue; 8 | import net.minecraft.resources.ResourceLocation; 9 | import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement; 10 | import org.jetbrains.annotations.Nullable; 11 | import org.objectweb.asm.Opcodes; 12 | import org.spongepowered.asm.mixin.Final; 13 | import org.spongepowered.asm.mixin.Mixin; 14 | import org.spongepowered.asm.mixin.Shadow; 15 | import org.spongepowered.asm.mixin.Unique; 16 | import org.spongepowered.asm.mixin.injection.At; 17 | 18 | @Mixin(StructurePlacement.class) 19 | public abstract class StructurePlacementMixin implements StructurifyStructurePlacement 20 | { 21 | @Shadow 22 | @Final 23 | private int salt; 24 | 25 | @Shadow 26 | @Final 27 | private float frequency; 28 | 29 | @Unique 30 | @Nullable 31 | public ResourceLocation structurify$structureIdentifier = null; 32 | 33 | public void structurify$setStructureSetIdentifier(ResourceLocation structureSetIdentifier) { 34 | this.structurify$structureIdentifier = structureSetIdentifier; 35 | } 36 | 37 | @Nullable 38 | public ResourceLocation structurify$getStructureSetIdentifier() { 39 | return this.structurify$structureIdentifier; 40 | } 41 | 42 | public int structurify$getOriginalSalt() { 43 | return this.salt; 44 | } 45 | 46 | public float structurify$getOriginalFrequency() { 47 | return this.frequency; 48 | } 49 | 50 | @ModifyReturnValue( 51 | method = "salt", 52 | at = @At("RETURN") 53 | ) 54 | protected int structurify$getSalt(int originalSalt) { 55 | return RandomSpreadUtil.getModifiedSalt(this.structurify$getStructureSetIdentifier(), originalSalt); 56 | } 57 | 58 | @ModifyReturnValue( 59 | method = "frequency", 60 | at = @At("RETURN") 61 | ) 62 | protected float structurify$getFrequency(float originalFrequency) { 63 | return RandomSpreadUtil.getModifiedFrequency(this.structurify$getStructureSetIdentifier(), originalFrequency); 64 | } 65 | 66 | //? >= 1.21.1 { 67 | @ModifyExpressionValue( 68 | method = "applyAdditionalChunkRestrictions", 69 | at = @At( 70 | value = "FIELD", 71 | target = "Lnet/minecraft/world/level/levelgen/structure/placement/StructurePlacement;frequency:F", 72 | opcode = Opcodes.GETFIELD 73 | ) 74 | ) 75 | protected float structurify$applyAdditionalChunkRestrictionsGetFrequency(float originalFrequency) { 76 | return Structurify.getConfig().getStructureSetData().get(this.structurify$getStructureSetIdentifier().toString()).getFrequency(); 77 | } 78 | //?} else { 79 | /*@ModifyExpressionValue( 80 | method = "isStructureChunk", 81 | at = @At( 82 | value = "FIELD", 83 | target = "Lnet/minecraft/world/level/levelgen/structure/placement/StructurePlacement;frequency:F", 84 | opcode = Opcodes.GETFIELD 85 | ) 86 | ) 87 | protected float structurify$isStructureChunkGetFrequency(float originalFrequency) { 88 | return Structurify.getConfig().getStructureSetData().get(this.structurify$getStructureSetIdentifier().toString()).getFrequency(); 89 | } 90 | *///?} 91 | } 92 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/yacl/CategoryTabAccessor.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin.yacl; 2 | 3 | import dev.isxander.yacl3.gui.OptionListWidget; 4 | import dev.isxander.yacl3.gui.SearchFieldWidget; 5 | import dev.isxander.yacl3.gui.YACLScreen; 6 | import dev.isxander.yacl3.gui.tab.ListHolderWidget; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.gen.Accessor; 9 | 10 | @Mixin(value = YACLScreen.CategoryTab.class, remap = false) 11 | public interface CategoryTabAccessor 12 | { 13 | @Accessor 14 | ListHolderWidget getOptionList(); 15 | 16 | @Accessor 17 | SearchFieldWidget getSearchField(); 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/yacl/SearchFieldWidgetInvoker.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin.yacl; 2 | 3 | import dev.isxander.yacl3.gui.SearchFieldWidget; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.gen.Invoker; 6 | 7 | @Mixin(value = SearchFieldWidget.class, remap = false) 8 | public interface SearchFieldWidgetInvoker 9 | { 10 | @Invoker("update") 11 | void structurify$invokeUpdate(String query); 12 | } 13 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/mixin/yacl/YACLScreenMixin.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.mixin.yacl; 2 | 3 | import com.faboslav.structurify.common.StructurifyClient; 4 | import dev.isxander.yacl3.gui.YACLScreen; 5 | import net.minecraft.client.gui.screens.Screen; 6 | import net.minecraft.network.chat.Component; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Inject; 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 11 | 12 | 13 | @Mixin(value = YACLScreen.class) 14 | public abstract class YACLScreenMixin extends Screen 15 | { 16 | protected YACLScreenMixin(Component component) { 17 | super(component); 18 | } 19 | 20 | @Inject( 21 | method = "onClose", 22 | at = @At("HEAD") 23 | ) 24 | public void structurify$onCloseHead(CallbackInfo ci) { 25 | if (this.minecraft != null) { 26 | if (this.minecraft.screen instanceof YACLScreen yaclsScreen) { 27 | var configScreen = StructurifyClient.getConfigScreen(); 28 | 29 | if (configScreen != null) { 30 | configScreen.saveScreenState(yaclsScreen); 31 | } 32 | } 33 | } 34 | } 35 | 36 | @Inject( 37 | method = "onClose", 38 | at = @At("TAIL") 39 | ) 40 | public void structurify$onCloseTail(CallbackInfo ci) { 41 | if (this.minecraft != null) { 42 | if (this.minecraft.screen instanceof YACLScreen yaclsScreen) { 43 | var configScreen = StructurifyClient.getConfigScreen(); 44 | 45 | if (configScreen != null) { 46 | configScreen.loadScreenState(yaclsScreen); 47 | } 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/modcompat/GlobalPacksCompat.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.modcompat; 2 | 3 | //? global_packs { 4 | 5 | /*import net.dark_roleplay.gdarp.CommonClass; 6 | import net.minecraft.server.packs.PackType; 7 | import net.minecraft.server.packs.repository.RepositorySource; 8 | 9 | import java.util.ArrayList; 10 | import java.util.EnumSet; 11 | 12 | public final class GlobalPacksCompat implements ModCompat 13 | { 14 | @Override 15 | public EnumSet compatTypes() { 16 | return EnumSet.of(Type.CUSTOM_RESOURCE_PACK_PROVIDERS); 17 | } 18 | 19 | @Override 20 | public ArrayList getResourcePackProviders() { 21 | var resourcePackProviders = new ArrayList(); 22 | 23 | resourcePackProviders.add(CommonClass.getRepositorySource(PackType.SERVER_DATA, true)); 24 | resourcePackProviders.add(CommonClass.getRepositorySource(PackType.SERVER_DATA, false)); 25 | 26 | return resourcePackProviders; 27 | } 28 | } 29 | *///?} 30 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/modcompat/ModChecker.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.modcompat; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.platform.PlatformHooks; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.function.Supplier; 9 | 10 | /** 11 | * Related code is based on The Bumblezone/Resourceful Lib mods with permissions from the authors 12 | * 13 | * @author TelepathicGrunt 14 | * https://github.com/TelepathicGrunt/Bumblezone 15 | * @author ThatGravyBoat 16 | * https://github.com/Team-Resourceful/ResourcefulLib 17 | */ 18 | public final class ModChecker 19 | { 20 | public static final List CUSTOM_RESOURCE_PACK_PROVIDER_COMPATS = new ArrayList<>(); 21 | public static final List BIOME_REPLACER_COMPATS = new ArrayList<>(); 22 | 23 | public static void setupModCompat() { 24 | String modId = ""; 25 | 26 | try { 27 | //? global_packs { 28 | /*loadModCompat("globalpacks", () -> new GlobalPacksCompat()); 29 | *///?} 30 | 31 | //? open_loader { 32 | /*loadModCompat("openloader", () -> new OpenLoaderCompat()); 33 | *///?} 34 | 35 | loadModCompat("terra", () -> new TerraCompat()); 36 | 37 | PlatformHooks.PLATFORM_COMPAT.setupPlatformModCompat(); 38 | } catch (Throwable e) { 39 | Structurify.getLogger().error("Failed to setup mod compats"); 40 | e.printStackTrace(); 41 | } 42 | } 43 | 44 | public static void loadModCompat(String modId, Supplier loader) { 45 | try { 46 | if (PlatformHooks.PLATFORM_HELPER.isModLoaded(modId)) { 47 | ModCompat compat = loader.get(); 48 | if (compat.compatTypes().contains(ModCompat.Type.CUSTOM_RESOURCE_PACK_PROVIDERS)) { 49 | CUSTOM_RESOURCE_PACK_PROVIDER_COMPATS.add(compat); 50 | } 51 | if (compat.compatTypes().contains(ModCompat.Type.BIOME_REPLACER)) { 52 | BIOME_REPLACER_COMPATS.add(compat); 53 | } 54 | } 55 | } catch (Throwable e) { 56 | Structurify.getLogger().error("Failed to load compat with " + modId); 57 | e.printStackTrace(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/modcompat/ModCompat.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.modcompat; 2 | 3 | import net.minecraft.server.packs.repository.RepositorySource; 4 | 5 | import java.util.ArrayList; 6 | import java.util.EnumSet; 7 | import java.util.List; 8 | 9 | /** 10 | * Related code is based on The Bumblezone/Resourceful Lib mods with permissions from the authors 11 | * 12 | * @author TelepathicGrunt 13 | * https://github.com/TelepathicGrunt/Bumblezone 14 | * @author ThatGravyBoat 15 | * https://github.com/Team-Resourceful/ResourcefulLib 16 | */ 17 | public interface ModCompat 18 | { 19 | default EnumSet compatTypes() { 20 | return EnumSet.noneOf(Type.class); 21 | } 22 | 23 | default ArrayList getResourcePackProviders() { 24 | return new ArrayList<>(); 25 | } 26 | 27 | default List getReplacedBiomes(List biomes) { 28 | return new ArrayList<>(); 29 | } 30 | 31 | enum Type 32 | { 33 | CUSTOM_RESOURCE_PACK_PROVIDERS, 34 | BIOME_REPLACER, 35 | MOD 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/modcompat/OpenLoaderCompat.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.modcompat; 2 | 3 | 4 | //? open_loader { 5 | /*import net.minecraft.server.packs.repository.RepositorySource; 6 | 7 | import java.util.ArrayList; 8 | import java.util.EnumSet; 9 | import java.nio.file.Paths; 10 | import java.nio.file.InvalidPathException; 11 | 12 | //? <=1.20.1 { 13 | /^import net.darkhax.openloader.config.ConfigSchema; 14 | import net.darkhax.openloader.packs.OpenLoaderRepositorySource; 15 | import net.darkhax.openloader.packs.RepoType; 16 | import com.faboslav.structurify.common.platform.PlatformHooks; 17 | ^///?} else { 18 | import net.darkhax.openloader.common.impl.packs.OpenLoaderRepositorySource; 19 | import net.minecraft.server.packs.PackType; 20 | import java.util.LinkedList; 21 | import java.io.File; 22 | import net.darkhax.openloader.common.impl.Platform; 23 | import net.darkhax.openloader.common.impl.OpenLoader; 24 | //?} 25 | 26 | public final class OpenLoaderCompat implements ModCompat 27 | { 28 | @Override 29 | public EnumSet compatTypes() { 30 | return EnumSet.of(Type.CUSTOM_RESOURCE_PACK_PROVIDERS); 31 | } 32 | 33 | @Override 34 | public ArrayList getResourcePackProviders() { 35 | var resourcePackProviders = new ArrayList(); 36 | 37 | //? <=1.20.1 { 38 | /^var configDir = PlatformHooks.PLATFORM_HELPER.getConfigDirectory().resolve("openloader"); 39 | ^///?} else { 40 | //?} 41 | 42 | return resourcePackProviders; 43 | } 44 | 45 | private static boolean isValidPath(String path) { 46 | try { 47 | Paths.get(path); 48 | } catch (InvalidPathException | NullPointerException ex) { 49 | return false; 50 | } 51 | return true; 52 | } 53 | } 54 | *///?} 55 | 56 | //var config = ConfigSchema.load(configDir); 57 | //resourcePackProviders.add(new OpenLoaderRepositorySource(RepoType.DATA, config, config.dataPacks, configDir)); 58 | //resourcePackProviders.add(OpenLoader.DATA_SOURCE.get()); -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/modcompat/TerraCompat.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.modcompat; 2 | 3 | import net.minecraft.resources.ResourceLocation; 4 | 5 | import java.lang.reflect.Method; 6 | import java.util.ArrayList; 7 | import java.util.EnumSet; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public final class TerraCompat implements ModCompat 12 | { 13 | @Override 14 | public EnumSet compatTypes() { 15 | return EnumSet.of(Type.BIOME_REPLACER); 16 | } 17 | 18 | @Override 19 | public List getReplacedBiomes(List biomes) { 20 | var terraBiomes = new ArrayList(); 21 | var terraBiomeMap = this.getTerraBiomes("com.dfsek.terra.mod.util.BiomeUtil", "getTerraBiomeMap"); 22 | 23 | if (terraBiomeMap == null) { 24 | terraBiomeMap = this.getTerraBiomes("com.dfsek.terra.mod.util.MinecraftUtil", "getTerraBiomeMap"); 25 | } 26 | 27 | if (terraBiomeMap != null) { 28 | terraBiomeMap.forEach((originalBiome, replacementBiomes) -> { 29 | var vanillaBiomeName = originalBiome.toString(); 30 | 31 | if (biomes.contains(vanillaBiomeName)) { 32 | for (var replacementBiome : replacementBiomes) { 33 | terraBiomes.add(replacementBiome.toString()); 34 | } 35 | } 36 | }); 37 | } 38 | 39 | return terraBiomes; 40 | } 41 | 42 | public Map> getTerraBiomes(String className, String methodName) { 43 | try { 44 | Class clazz = Class.forName(className); 45 | Method method = clazz.getDeclaredMethod(methodName); 46 | method.setAccessible(true); 47 | Object result = method.invoke(null); 48 | return (Map>) result; 49 | 50 | } catch (Exception e) { 51 | return null; 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/platform/PlatformCompat.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.platform; 2 | 3 | public interface PlatformCompat 4 | { 5 | void setupPlatformModCompat(); 6 | } 7 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/platform/PlatformHelper.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.platform; 2 | 3 | import java.nio.file.Path; 4 | 5 | public interface PlatformHelper 6 | { 7 | boolean isModLoaded(String modId); 8 | 9 | String getModVersion(); 10 | 11 | Path getConfigDirectory(); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/platform/PlatformHooks.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.platform; 2 | 3 | import java.util.ServiceLoader; 4 | 5 | public final class PlatformHooks 6 | { 7 | public static final PlatformCompat PLATFORM_COMPAT = load(PlatformCompat.class); 8 | public static final PlatformHelper PLATFORM_HELPER = load(PlatformHelper.class); 9 | public static final PlatformResourcePackProvider PLATFORM_RESOURCE_PACK_PROVIDER = load(PlatformResourcePackProvider.class); 10 | 11 | public static T load(Class service) { 12 | T loadedService = ServiceLoader.load(service) 13 | .findFirst() 14 | .orElseThrow(() -> new NullPointerException("No implementation found for " + service.getName())); 15 | return loadedService; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/platform/PlatformResourcePackProvider.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.platform; 2 | 3 | import net.minecraft.server.packs.repository.RepositorySource; 4 | 5 | import java.util.ArrayList; 6 | 7 | public interface PlatformResourcePackProvider 8 | { 9 | ArrayList getPlatformResourcePackProviders(); 10 | } 11 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/registry/StructurifyRegistryManagerProvider.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.registry; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.mojang.serialization.Lifecycle; 5 | import net.minecraft.Util; 6 | import net.minecraft.commands.Commands; 7 | import net.minecraft.core.HolderLookup; 8 | import net.minecraft.core.MappedRegistry; 9 | import net.minecraft.core.registries.Registries; 10 | import net.minecraft.server.WorldLoader; 11 | import net.minecraft.server.WorldStem; 12 | import net.minecraft.server.packs.repository.PackRepository; 13 | import net.minecraft.server.packs.repository.RepositorySource; 14 | import net.minecraft.world.level.WorldDataConfiguration; 15 | import net.minecraft.world.level.biome.Biome; 16 | import net.minecraft.world.level.levelgen.presets.WorldPresets; 17 | import net.minecraft.world.level.storage.PrimaryLevelData; 18 | import org.jetbrains.annotations.Nullable; 19 | 20 | public final class StructurifyRegistryManagerProvider 21 | { 22 | @Nullable 23 | private static HolderLookup.Provider registryManager = null; 24 | private static boolean isLoading = false; 25 | 26 | @Nullable 27 | public static HolderLookup.Provider getRegistryManager() { 28 | if (registryManager == null) { 29 | loadRegistryManager(); 30 | } 31 | 32 | return registryManager; 33 | } 34 | 35 | @Nullable 36 | public static HolderLookup.RegistryLookup getBiomeRegistry() { 37 | var registryManager = StructurifyRegistryManagerProvider.getRegistryManager(); 38 | 39 | if (registryManager == null) { 40 | return null; 41 | } 42 | 43 | var biomeRegistry = registryManager.lookup(Registries.BIOME).orElse(null); 44 | 45 | if (biomeRegistry == null) { 46 | return null; 47 | } 48 | 49 | return biomeRegistry; 50 | } 51 | 52 | public static void setRegistryManager(HolderLookup.Provider registryAccess) { 53 | registryManager = registryAccess; 54 | } 55 | 56 | public static void loadRegistryManager() { 57 | if (isLoading) { 58 | return; 59 | } 60 | 61 | isLoading = true; 62 | try { 63 | Structurify.getLogger().info("Loading registry manager..."); 64 | var resourcePackProviders = StructurifyResourcePackProvider.getResourcePackProviders(); 65 | 66 | for (var resourcePackProvider : resourcePackProviders) { 67 | Structurify.getLogger().info("Registering resource pack provider: " + resourcePackProvider.getClass().getSimpleName()); 68 | } 69 | 70 | var resourcePackManager = new PackRepository(StructurifyResourcePackProvider.getResourcePackProviders().toArray(new RepositorySource[0])); 71 | var dataPacks = new WorldLoader.PackConfig(resourcePackManager, WorldDataConfiguration.DEFAULT, false, false); 72 | var serverConfig = new WorldLoader.InitConfig(dataPacks, Commands.CommandSelection.INTEGRATED, 2); 73 | 74 | var saveLoader = Util.blockUntilDone(executor -> 75 | WorldLoader.load(serverConfig, loadContextSupplierContext -> { 76 | var registry = new MappedRegistry<>(Registries.LEVEL_STEM, Lifecycle.stable()).freeze(); 77 | 78 | //? >=1.21.3 { 79 | var dimensionsConfig = loadContextSupplierContext 80 | .datapackWorldgen() 81 | .lookupOrThrow(Registries.WORLD_PRESET) 82 | .getOrThrow(WorldPresets.FLAT) 83 | .value() 84 | .createWorldDimensions() 85 | .bake(registry); 86 | //?} else { 87 | /*var dimensionsConfig = loadContextSupplierContext 88 | .datapackWorldgen() 89 | .registryOrThrow(Registries.WORLD_PRESET) 90 | .getHolderOrThrow(WorldPresets.FLAT) 91 | .value() 92 | .createWorldDimensions() 93 | .bake(registry); 94 | *///?} 95 | 96 | return new WorldLoader.DataLoadOutput(null, dimensionsConfig.dimensionsRegistryAccess()); 97 | }, WorldStem::new, Util.backgroundExecutor(), executor) 98 | ).get(); 99 | 100 | if (saveLoader == null || saveLoader.registries() == null) { 101 | Structurify.getLogger().error("SaveLoader or CombinedDynamicRegistries is null."); 102 | return; 103 | } 104 | 105 | setRegistryManager(saveLoader.registries().compositeAccess()); 106 | Structurify.getLogger().info("Finished loading registry manager"); 107 | } catch (Exception exception) { 108 | Structurify.getLogger().error("Failed to load registry manager.", exception); 109 | } finally { 110 | isLoading = false; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/registry/StructurifyRegistryUpdater.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.registry; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.api.StructurifyStructure; 5 | import com.faboslav.structurify.common.api.StructurifyStructurePlacement; 6 | import com.faboslav.structurify.common.events.common.UpdateRegistriesEvent; 7 | import net.minecraft.core.HolderLookup; 8 | import net.minecraft.core.registries.Registries; 9 | import net.minecraft.resources.ResourceLocation; 10 | 11 | public final class StructurifyRegistryUpdater 12 | { 13 | public static void updateRegistries(final UpdateRegistriesEvent event) { 14 | if (!Structurify.getConfig().isLoaded) { 15 | return; 16 | } 17 | 18 | try { 19 | Structurify.getLogger().info("Updating registries..."); 20 | var registryManager = event.registryManager(); 21 | 22 | if (registryManager == null) { 23 | return; 24 | } 25 | 26 | StructurifyRegistryUpdater.updateStructures(registryManager); 27 | StructurifyRegistryUpdater.updateStructureSets(registryManager); 28 | Structurify.getLogger().info("Registries updated"); 29 | } catch (Exception e) { 30 | Structurify.getLogger().info("Failed to update registries"); 31 | } 32 | } 33 | 34 | private static void updateStructures(HolderLookup.Provider registryManager) { 35 | var structureRegistry = registryManager.lookup(Registries.STRUCTURE).orElse(null); 36 | 37 | if (structureRegistry == null) { 38 | return; 39 | } 40 | 41 | for (var structureReference : structureRegistry.listElements().toList()) { 42 | var structure = structureReference.value(); 43 | var structureRegistryKey = structureReference.key(); 44 | 45 | ResourceLocation structureId = structureRegistryKey.location(); 46 | var structurifyStructure = ((StructurifyStructure) structure); 47 | structurifyStructure.structurify$setStructureIdentifier(structureId); 48 | structurifyStructure.structurify$setStructureBiomes(null); 49 | } 50 | 51 | Structurify.getLogger().info("Structure registries updated"); 52 | } 53 | 54 | private static void updateStructureSets(HolderLookup.Provider registryManager) { 55 | var structureSetRegistry = registryManager.lookup(Registries.STRUCTURE_SET).orElse(null); 56 | 57 | if (structureSetRegistry == null) { 58 | return; 59 | } 60 | 61 | for (var structureSetReference : structureSetRegistry.listElements().toList()) { 62 | var structureSet = structureSetReference.value(); 63 | var structureSetRegistryKey = structureSetReference.key(); 64 | 65 | ResourceLocation structureSetId = structureSetRegistryKey.location(); 66 | StructurifyStructurePlacement structurifyStructurePlacement = ((StructurifyStructurePlacement) structureSet.placement()); 67 | structurifyStructurePlacement.structurify$setStructureSetIdentifier(structureSetId); 68 | } 69 | 70 | Structurify.getLogger().info("Structure Sets registries updated"); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/registry/StructurifyResourcePackProvider.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.registry; 2 | 3 | import com.faboslav.structurify.common.modcompat.ModChecker; 4 | import com.faboslav.structurify.common.modcompat.ModCompat; 5 | import com.faboslav.structurify.common.platform.PlatformHooks; 6 | import net.minecraft.server.packs.repository.RepositorySource; 7 | import net.minecraft.server.packs.repository.ServerPacksSource; 8 | 9 | import java.util.ArrayList; 10 | 11 | //? >=1.21 { 12 | import com.faboslav.structurify.common.mixin.ResourcePackManagerAccessor; 13 | //?} 14 | 15 | public final class StructurifyResourcePackProvider 16 | { 17 | public static ArrayList getResourcePackProviders() { 18 | ArrayList resourcePackProviders = new ArrayList<>(); 19 | 20 | resourcePackProviders.addAll(getVanillaResourcePackProviders()); 21 | resourcePackProviders.addAll(PlatformHooks.PLATFORM_RESOURCE_PACK_PROVIDER.getPlatformResourcePackProviders()); 22 | resourcePackProviders.addAll(getModsResourcePackProviders()); 23 | 24 | return resourcePackProviders; 25 | } 26 | 27 | public static ArrayList getVanillaResourcePackProviders() { 28 | ArrayList vanillaResourcePackProviders = new ArrayList<>(); 29 | 30 | //? >=1.21 { 31 | vanillaResourcePackProviders.addAll(((ResourcePackManagerAccessor) ServerPacksSource.createVanillaTrustedRepository()).getSources()); 32 | //?} else { 33 | /*vanillaResourcePackProviders.add(new ServerPacksSource()); 34 | *///?} 35 | 36 | return vanillaResourcePackProviders; 37 | } 38 | 39 | public static ArrayList getModsResourcePackProviders() { 40 | ArrayList modResourcePackProviders = new ArrayList<>(); 41 | 42 | for (ModCompat compat : ModChecker.CUSTOM_RESOURCE_PACK_PROVIDER_COMPATS) { 43 | var resourcePackProviders = compat.getResourcePackProviders(); 44 | modResourcePackProviders.addAll(resourcePackProviders); 45 | } 46 | 47 | return modResourcePackProviders; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/util/LanguageUtil.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.util; 2 | 3 | import net.minecraft.locale.Language; 4 | import net.minecraft.network.chat.Component; 5 | import net.minecraft.network.chat.MutableComponent; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | import java.util.regex.Pattern; 9 | 10 | public final class LanguageUtil 11 | { 12 | private static final String FIRST_LETTER_REGEX = "\\b(.)(.*?)\\b"; 13 | private static final Pattern FIRST_LETTER_PATTERN = Pattern.compile(FIRST_LETTER_REGEX); 14 | 15 | public static MutableComponent translateId(@Nullable String prefix, String id) { 16 | String langKey = transformToLangKey(prefix, id); 17 | Language language = Language.getInstance(); 18 | 19 | if (!language.has(langKey)) { 20 | if (prefix == null) { 21 | langKey = id; 22 | } else if (id.contains(":")) { 23 | langKey = id.split(":")[1]; 24 | } 25 | 26 | langKey = langKey.replace("_", " ").replace("/", " "); 27 | 28 | langKey = FIRST_LETTER_PATTERN 29 | .matcher(langKey) 30 | .replaceAll(matchResult -> matchResult.group(1).toUpperCase() + matchResult.group(2)); 31 | } 32 | 33 | return Component.translatable(langKey); 34 | } 35 | 36 | private static String transformToLangKey(@Nullable String prefix, String identifier) { 37 | if (prefix == null) { 38 | return identifier.replace(":", "."); 39 | } 40 | 41 | return prefix + "." + identifier.replace(":", "."); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/src/main/java/com/faboslav/structurify/common/util/RandomSpreadUtil.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.common.util; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.config.data.StructureSetData; 5 | import net.minecraft.resources.ResourceLocation; 6 | 7 | public final class RandomSpreadUtil 8 | { 9 | private static StructureSetData getStructureSetData(ResourceLocation structureSetIdentifier) { 10 | if (structureSetIdentifier == null || !Structurify.getConfig().getStructureSetData().containsKey(structureSetIdentifier.toString())) { 11 | return null; 12 | } 13 | 14 | return Structurify.getConfig().getStructureSetData().get(structureSetIdentifier.toString()); 15 | } 16 | 17 | public static int getModifiedSalt(ResourceLocation structureSetIdentifier, int originalSalt) { 18 | StructureSetData structureSetData = getStructureSetData(structureSetIdentifier); 19 | 20 | if (structureSetData == null) { 21 | return originalSalt; 22 | } 23 | 24 | return structureSetData.getSalt(); 25 | } 26 | 27 | public static float getModifiedFrequency(ResourceLocation structureSetIdentifier, float originalFrequency) { 28 | StructureSetData structureSetData = getStructureSetData(structureSetIdentifier); 29 | 30 | if (structureSetData == null) { 31 | return originalFrequency; 32 | } 33 | 34 | return structureSetData.getFrequency(); 35 | } 36 | 37 | public static int getModifiedSpacing(ResourceLocation structureSetIdentifier, int originalSpacing) { 38 | StructureSetData structureSetData = getStructureSetData(structureSetIdentifier); 39 | return getModifiedSpacing(structureSetData, originalSpacing); 40 | } 41 | 42 | public static int getModifiedSpacing(StructureSetData structureSetData, int originalSpacing) { 43 | int spacing = originalSpacing; 44 | 45 | if (Structurify.getConfig().enableGlobalSpacingAndSeparationModifier) { 46 | if (structureSetData != null && structureSetData.overrideGlobalSpacingAndSeparationModifier()) { 47 | spacing = structureSetData.getSpacing(); 48 | } else { 49 | spacing = (int) (spacing * Structurify.getConfig().globalSpacingAndSeparationModifier); 50 | } 51 | } else if (structureSetData != null) { 52 | spacing = structureSetData.getSpacing(); 53 | } 54 | 55 | return getCorrectedModifiedSpacingValue(spacing); 56 | } 57 | 58 | public static int getModifiedSeparation( 59 | ResourceLocation structureSetIdentifier, 60 | int spacing, 61 | int originalSeparation 62 | ) { 63 | StructureSetData structureSetData = getStructureSetData(structureSetIdentifier); 64 | return getModifiedSeparation(structureSetData, spacing, originalSeparation); 65 | } 66 | 67 | public static int getModifiedSeparation( 68 | StructureSetData structureSetData, 69 | int spacing, 70 | int originalSeparation 71 | ) { 72 | int separation = originalSeparation; 73 | 74 | if (Structurify.getConfig().enableGlobalSpacingAndSeparationModifier) { 75 | if (structureSetData != null && structureSetData.overrideGlobalSpacingAndSeparationModifier()) { 76 | separation = structureSetData.getSeparation(); 77 | } else { 78 | separation = (int) (separation * Structurify.getConfig().globalSpacingAndSeparationModifier); 79 | } 80 | } else if (structureSetData != null) { 81 | separation = structureSetData.getSeparation(); 82 | } 83 | 84 | return getCorrectedModifiedSeparationValue(spacing, separation); 85 | } 86 | 87 | private static int getCorrectedModifiedSpacingValue(int spacingValue) { 88 | return Math.max(1, spacingValue); 89 | } 90 | 91 | private static int getCorrectedModifiedSeparationValue(int spacing, int separation) { 92 | separation = Math.max(0, separation); 93 | 94 | if (separation >= spacing) { 95 | separation = spacing - 1; 96 | } 97 | 98 | return separation; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/badlands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/badlands.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/badlands_plateau.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/badlands_plateau.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/bamboo_jungle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/bamboo_jungle.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/basalt_deltas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/basalt_deltas.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/beach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/beach.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/birch_forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/birch_forest.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/cherry_grove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/cherry_grove.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/cold_ocean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/cold_ocean.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/crimson_forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/crimson_forest.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/dark_forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/dark_forest.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_cold_ocean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_cold_ocean.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_dark.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_frozen_ocean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_frozen_ocean.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_lukewarm_ocean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_lukewarm_ocean.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_ocean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_ocean.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_warm_ocean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/deep_warm_ocean.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/desert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/desert.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/desert_lakes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/desert_lakes.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/dripstone_caves.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/dripstone_caves.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/end_barrens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/end_barrens.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/end_highlands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/end_highlands.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/end_midlands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/end_midlands.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/eroded_badlands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/eroded_badlands.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/flower_forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/flower_forest.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/forest.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/frozen_ocean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/frozen_ocean.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/frozen_peaks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/frozen_peaks.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/frozen_river.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/frozen_river.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/grove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/grove.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/ice_spikes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/ice_spikes.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/jagged_peaks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/jagged_peaks.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/jungle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/jungle.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/lukewarm_ocean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/lukewarm_ocean.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/lush_caves.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/lush_caves.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/mangrove_swamp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/mangrove_swamp.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/meadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/meadow.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/mountain_edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/mountain_edge.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/mushroom_fields.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/mushroom_fields.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/nether_wastes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/nether_wastes.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/ocean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/ocean.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/old_growth_birch_forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/old_growth_birch_forest.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/old_growth_pine_taiga.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/old_growth_pine_taiga.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/old_growth_spruce_taiga.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/old_growth_spruce_taiga.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/plains.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/plains.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/river.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/river.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/savanna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/savanna.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/savanna_plateau.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/savanna_plateau.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/small_end_islands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/small_end_islands.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/snowy_beach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/snowy_beach.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/snowy_plains.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/snowy_plains.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/snowy_slopes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/snowy_slopes.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/snowy_taiga.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/snowy_taiga.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/soul_sand_valley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/soul_sand_valley.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/sparse_jungle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/sparse_jungle.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/stony_peaks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/stony_peaks.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/stony_shore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/stony_shore.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/sunflower_plains.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/sunflower_plains.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/swamp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/swamp.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/taiga.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/taiga.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/the_end.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/the_end.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/the_void.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/the_void.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/unknown.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/warm_ocean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/warm_ocean.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/warped_forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/warped_forest.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/windswept_forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/windswept_forest.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/windswept_gravelly_hills.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/windswept_gravelly_hills.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/windswept_hills.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/windswept_hills.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/windswept_savanna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/windswept_savanna.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/wooded_badlands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/biomes/wooded_badlands.png -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/buttons/structure_sets.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/buttons/structure_sets.webp -------------------------------------------------------------------------------- /common/src/main/resources/assets/structurify/textures/gui/config/images/buttons/structures.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/assets/structurify/textures/gui/config/images/buttons/structures.webp -------------------------------------------------------------------------------- /common/src/main/resources/catalogue_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/catalogue_background.png -------------------------------------------------------------------------------- /common/src/main/resources/catalogue_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/catalogue_icon.png -------------------------------------------------------------------------------- /common/src/main/resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/common/src/main/resources/icon.png -------------------------------------------------------------------------------- /common/src/main/resources/structurify-common.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "com.faboslav.structurify.common.mixin", 4 | "refmap": "${modId}.refmap.json", 5 | "compatibilityLevel": "JAVA_${javaVersion}", 6 | "minVersion": "0.8", 7 | "plugin": "com.faboslav.structurify.common.mixin.plugin.StructurifyMixinPlugin", 8 | "injectors": { 9 | "defaultRequire": 1 10 | }, 11 | "mixins": [ 12 | "ChunkGeneratorMixin", 13 | "LocateCommandMixin", 14 | "ResourcePackManagerAccessor", 15 | "compat.RepurposedStructuresModifySpreadMixin", 16 | "structure.StructureMixin", 17 | "structure.jigsaw.JigsawStructureMixin", 18 | "structure.jigsaw.MaxDistanceFromCenterAccessor", 19 | "structure.placement.RandomSpreadStructurePlacementMixin", 20 | "structure.placement.StructurePlacementMixin" 21 | ], 22 | "client": [ 23 | "AbstractWidgetInvoker", 24 | "WorldOpenFlowsMixin", 25 | "yacl.CategoryTabAccessor", 26 | "yacl.SearchFieldWidgetInvoker", 27 | "yacl.YACLScreenMixin" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /fabric/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("fabric-loom") 3 | `multiloader-loader` 4 | id("dev.kikugie.j52j") version "2.0" 5 | } 6 | 7 | stonecutter { 8 | const("terra", rootProject.project(stonecutter.current.project).property("deps.terra").toString() != "") 9 | } 10 | 11 | dependencies { 12 | minecraft("com.mojang:minecraft:${commonMod.mc}") 13 | mappings(loom.layered { 14 | officialMojangMappings() 15 | commonMod.depOrNull("parchment")?.let { parchmentVersion -> 16 | parchment("org.parchmentmc.data:parchment-${commonMod.mc}:$parchmentVersion@zip") 17 | } 18 | }) 19 | 20 | modImplementation("net.fabricmc:fabric-loader:${commonMod.dep("fabric_loader")}") 21 | modApi("net.fabricmc.fabric-api:fabric-api:${commonMod.dep("fabric_api")}+${commonMod.mc}") 22 | 23 | // Required dependencies 24 | modImplementation("dev.isxander:yet-another-config-lib:${commonMod.dep("yacl")}-fabric") 25 | modImplementation("com.terraformersmc:modmenu:${commonMod.dep("mod_menu")}") 26 | 27 | 28 | // Global DataPacks 29 | commonMod.depOrNull("global_datapacks")?.let { globalDatapacksVersion -> 30 | modCompileOnly(commonMod.modrinth("datapacks", globalDatapacksVersion)) { isTransitive = false } 31 | } 32 | 33 | // Global Packs 34 | commonMod.depOrNull("global_packs")?.let { globalPacksVersion -> 35 | if (commonMod.mc == "1.20.1") { 36 | modCompileOnly(commonMod.modrinth("globalpacks", "${globalPacksVersion}_fabric")) { isTransitive = false } 37 | } else { 38 | modCompileOnly(commonMod.modrinth("globalpacks", globalPacksVersion)) { isTransitive = false } 39 | } 40 | } 41 | 42 | // Open Loader 43 | commonMod.depOrNull("open_loader")?.let { openLoaderVersion -> 44 | if (commonMod.mc == "1.21.1") { 45 | modImplementation( 46 | group = "net.darkhax.openloader", 47 | name = "openloader-fabric-${commonMod.mc}", 48 | version = openLoaderVersion 49 | ) 50 | } else { 51 | modImplementation( 52 | group = "net.darkhax.openloader", 53 | name = "OpenLoader-Fabric-${commonMod.mc}", 54 | version = openLoaderVersion 55 | ) 56 | } 57 | } 58 | 59 | // Terra 60 | commonMod.depOrNull("terra")?.let { terraVersion -> 61 | modImplementation("com.dfsek.terra:fabric:${terraVersion}") 62 | } 63 | 64 | // Yungs api 65 | commonMod.depOrNull("yungs_api_minecraft")?.let { yungsApiMcVersion -> 66 | commonMod.depOrNull("yungs_api")?.let { yungsApiVersion -> 67 | modImplementation("com.yungnickyoung.minecraft.yungsapi:YungsApi:$yungsApiMcVersion-Fabric-$yungsApiVersion") 68 | } 69 | } 70 | 71 | // Repurposed structures 72 | commonMod.depOrNull("repurposed_structures")?.let { repurposedStructuresVersion -> 73 | commonMod.depOrNull("midnight_lib")?.let { midnightLibVersion -> 74 | modImplementation("com.telepathicgrunt:RepurposedStructures:${repurposedStructuresVersion}-fabric") 75 | if (commonMod.mc == "1.21.4" || commonMod.mc == "1.21.5") { 76 | modImplementation(commonMod.modrinth("midnightlib", "${midnightLibVersion}-fabric")) 77 | } else { 78 | modImplementation(commonMod.modrinth("midnightlib", "${midnightLibVersion}-fabric")) 79 | } 80 | } 81 | } 82 | } 83 | 84 | loom { 85 | runs { 86 | getByName("client") { 87 | client() 88 | configName = "Fabric Client" 89 | ideConfigGenerated(true) 90 | } 91 | getByName("server") { 92 | server() 93 | configName = "Fabric Server" 94 | ideConfigGenerated(true) 95 | } 96 | } 97 | 98 | mixin { 99 | defaultRefmapName = "${mod.id}.refmap.json" 100 | } 101 | } -------------------------------------------------------------------------------- /fabric/gradle.properties: -------------------------------------------------------------------------------- 1 | loader=fabric -------------------------------------------------------------------------------- /fabric/src/main/java/com/faboslav/structurify/fabric/StructurifyFabric.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.fabric; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.commands.DumpCommand; 5 | import com.faboslav.structurify.common.events.common.LoadConfigEvent; 6 | import com.faboslav.structurify.common.events.common.UpdateRegistriesEvent; 7 | import com.faboslav.structurify.common.registry.StructurifyRegistryManagerProvider; 8 | import net.fabricmc.api.ModInitializer; 9 | import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; 10 | import net.fabricmc.fabric.api.event.lifecycle.v1.CommonLifecycleEvents; 11 | import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; 12 | import net.minecraft.core.RegistryAccess; 13 | import net.minecraft.server.MinecraftServer; 14 | 15 | public final class StructurifyFabric implements ModInitializer 16 | { 17 | @Override 18 | public void onInitialize() { 19 | Structurify.init(); 20 | 21 | CommandRegistrationCallback.EVENT.register((dispatcher, buildContext, dedicated) -> DumpCommand.createCommand(dispatcher)); 22 | CommonLifecycleEvents.TAGS_LOADED.register(this::onDatapackReload); 23 | ServerLifecycleEvents.SERVER_STARTING.register(this::onServerStart); 24 | } 25 | 26 | private void onDatapackReload(RegistryAccess registryAccess, boolean isClient) { 27 | if (isClient) { 28 | return; 29 | } 30 | 31 | StructurifyRegistryManagerProvider.setRegistryManager(registryAccess); 32 | LoadConfigEvent.EVENT.invoke(new LoadConfigEvent()); 33 | } 34 | 35 | private void onServerStart(MinecraftServer minecraftServer) { 36 | StructurifyRegistryManagerProvider.setRegistryManager(minecraftServer.registryAccess()); 37 | UpdateRegistriesEvent.EVENT.invoke(new UpdateRegistriesEvent(StructurifyRegistryManagerProvider.getRegistryManager())); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/faboslav/structurify/fabric/StructurifyFabricClient.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.fabric; 2 | 3 | import com.faboslav.structurify.common.StructurifyClient; 4 | import net.fabricmc.api.ClientModInitializer; 5 | import net.fabricmc.api.EnvType; 6 | import net.fabricmc.api.Environment; 7 | 8 | public final class StructurifyFabricClient implements ClientModInitializer 9 | { 10 | @Override 11 | @Environment(EnvType.CLIENT) 12 | public void onInitializeClient() { 13 | StructurifyClient.init(); 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/faboslav/structurify/fabric/modcompat/CatalogueCompat.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.fabric.modcompat; 2 | 3 | import com.faboslav.structurify.common.StructurifyClient; 4 | import net.fabricmc.loader.api.FabricLoader; 5 | import net.fabricmc.loader.api.ModContainer; 6 | import net.minecraft.client.gui.screens.Screen; 7 | 8 | public final class CatalogueCompat 9 | { 10 | public static Screen createConfigScreen(Screen currentScreen, ModContainer container) { 11 | if ( 12 | !FabricLoader.getInstance().isModLoaded("catalogue") 13 | ) { 14 | return null; 15 | } 16 | 17 | return StructurifyClient.getConfigScreen(currentScreen); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/faboslav/structurify/fabric/modcompat/GlobalDatapacksCompat.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.fabric.modcompat; 2 | 3 | import com.faboslav.structurify.common.modcompat.ModCompat; 4 | import net.minecraft.server.packs.PackType; 5 | import net.minecraft.server.packs.repository.FolderRepositorySource; 6 | import net.minecraft.server.packs.repository.PackSource; 7 | import net.minecraft.server.packs.repository.RepositorySource; 8 | 9 | import java.lang.reflect.Field; 10 | import java.nio.file.Path; 11 | import java.util.ArrayList; 12 | import java.util.EnumSet; 13 | 14 | //? >1.20.1 { 15 | import net.minecraft.world.level.validation.DirectoryValidator; 16 | //?} 17 | 18 | public final class GlobalDatapacksCompat implements ModCompat 19 | { 20 | @Override 21 | public EnumSet compatTypes() { 22 | return EnumSet.of(Type.CUSTOM_RESOURCE_PACK_PROVIDERS); 23 | } 24 | 25 | @Override 26 | public ArrayList getResourcePackProviders() { 27 | var resourcePackProviders = new ArrayList(); 28 | 29 | try { 30 | Class globalDatapackClass = Class.forName("me.declipsonator.globaldatapack.GlobalDatapack"); 31 | Field globalPackFolderField = globalDatapackClass.getField("globalPackFolder"); 32 | Path globalPackFolder = (Path) globalPackFolderField.get(null); 33 | 34 | //? =1.20.1 { 35 | /*resourcePackProviders.add(new FolderRepositorySource(globalPackFolder, PackType.SERVER_DATA, PackSource.WORLD)); 36 | *///?} else { 37 | resourcePackProviders.add(new FolderRepositorySource(globalPackFolder, PackType.SERVER_DATA, PackSource.WORLD, new DirectoryValidator(path -> true))); 38 | //?} 39 | } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { 40 | System.out.println("Dependency not found or field access failed: " + e.getMessage()); 41 | } 42 | 43 | return resourcePackProviders; 44 | } 45 | } -------------------------------------------------------------------------------- /fabric/src/main/java/com/faboslav/structurify/fabric/modcompat/ModMenuCompat.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.fabric.modcompat; 2 | 3 | import com.faboslav.structurify.common.StructurifyClient; 4 | import com.terraformersmc.modmenu.api.ConfigScreenFactory; 5 | import com.terraformersmc.modmenu.api.ModMenuApi; 6 | import net.fabricmc.loader.api.FabricLoader; 7 | 8 | public final class ModMenuCompat implements ModMenuApi 9 | { 10 | @Override 11 | public ConfigScreenFactory getModConfigScreenFactory() { 12 | return (screen) -> { 13 | if ( 14 | !FabricLoader.getInstance().isModLoaded("modmenu") 15 | ) { 16 | return null; 17 | } 18 | 19 | return StructurifyClient.getConfigScreen(screen); 20 | }; 21 | } 22 | } -------------------------------------------------------------------------------- /fabric/src/main/java/com/faboslav/structurify/fabric/platform/FabricPlatformCompat.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.fabric.platform; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.platform.PlatformCompat; 5 | import com.faboslav.structurify.fabric.modcompat.GlobalDatapacksCompat; 6 | 7 | import static com.faboslav.structurify.common.modcompat.ModChecker.loadModCompat; 8 | 9 | public final class FabricPlatformCompat implements PlatformCompat 10 | { 11 | @Override 12 | public void setupPlatformModCompat() { 13 | String modId = ""; 14 | 15 | try { 16 | modId = "global-datapack"; 17 | loadModCompat(modId, () -> new GlobalDatapacksCompat()); 18 | } catch (Throwable e) { 19 | Structurify.getLogger().error("Failed to setup compat with " + modId); 20 | e.printStackTrace(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/faboslav/structurify/fabric/platform/FabricPlatformHelper.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.fabric.platform; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.platform.PlatformHelper; 5 | import net.fabricmc.loader.api.FabricLoader; 6 | 7 | import java.nio.file.Path; 8 | 9 | public final class FabricPlatformHelper implements PlatformHelper 10 | { 11 | @Override 12 | public boolean isModLoaded(String modId) { 13 | return FabricLoader.getInstance().isModLoaded(modId); 14 | } 15 | 16 | @Override 17 | public String getModVersion() { 18 | return FabricLoader.getInstance().getModContainer(Structurify.MOD_ID).map(modContainer -> modContainer.getMetadata().getVersion().toString()).orElse(null); 19 | } 20 | 21 | @Override 22 | public Path getConfigDirectory() { 23 | return FabricLoader.getInstance().getConfigDir(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /fabric/src/main/java/com/faboslav/structurify/fabric/platform/FabricPlatformResourcePackProvider.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.fabric.platform; 2 | 3 | import com.faboslav.structurify.common.platform.PlatformResourcePackProvider; 4 | import net.fabricmc.fabric.impl.resource.loader.ModResourcePackCreator; 5 | import net.minecraft.server.packs.PackType; 6 | import net.minecraft.server.packs.repository.RepositorySource; 7 | 8 | import java.util.ArrayList; 9 | 10 | public class FabricPlatformResourcePackProvider implements PlatformResourcePackProvider 11 | { 12 | public ArrayList getPlatformResourcePackProviders() { 13 | ArrayList platformResourcePackProviders = new ArrayList<>(); 14 | 15 | platformResourcePackProviders.add(new ModResourcePackCreator(PackType.SERVER_DATA)); 16 | 17 | return platformResourcePackProviders; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /fabric/src/main/resources/META-INF/services/com.faboslav.structurify.common.platform.PlatformCompat: -------------------------------------------------------------------------------- 1 | com.faboslav.structurify.fabric.platform.FabricPlatformCompat -------------------------------------------------------------------------------- /fabric/src/main/resources/META-INF/services/com.faboslav.structurify.common.platform.PlatformHelper: -------------------------------------------------------------------------------- 1 | com.faboslav.structurify.fabric.platform.FabricPlatformHelper -------------------------------------------------------------------------------- /fabric/src/main/resources/META-INF/services/com.faboslav.structurify.common.platform.PlatformResourcePackProvider: -------------------------------------------------------------------------------- 1 | com.faboslav.structurify.fabric.platform.FabricPlatformResourcePackProvider -------------------------------------------------------------------------------- /fabric/src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "${modId}", 4 | "version": "${modVersion}", 5 | "name": "${modName}", 6 | "description": "${modDescription}", 7 | "authors": [ 8 | "${modAuthor}" 9 | ], 10 | "contact": { 11 | "homepage": "https://github.com/Faboslav/structurify", 12 | "sources": "https://github.com/Faboslav/structurify", 13 | "issues": "https://github.com/Faboslav/structurify/issues", 14 | "discord": "https://discord.com/invite/QGwFvvMQCn" 15 | }, 16 | "license": "${modLicense}", 17 | "icon": "icon.png", 18 | "environment": "*", 19 | "entrypoints": { 20 | "main": [ 21 | "com.faboslav.structurify.fabric.StructurifyFabric" 22 | ], 23 | "client": [ 24 | "com.faboslav.structurify.fabric.StructurifyFabricClient" 25 | ], 26 | "modmenu": [ 27 | "com.faboslav.structurify.fabric.modcompat.ModMenuCompat" 28 | ] 29 | }, 30 | "mixins": [ 31 | "structurify-common.mixins.json", 32 | "structurify-fabric.mixins.json" 33 | ], 34 | "depends": { 35 | "minecraft": ">=${minMinecraftVersion}-", 36 | "fabricloader": "*", 37 | "fabric": "*", 38 | "yet_another_config_lib_v3": ">=${yaclVersion}", 39 | "modmenu": ">=${modMenuVersion}" 40 | }, 41 | "custom": { 42 | "modmenu": { 43 | "links": { 44 | "Discord": "https://discord.com/invite/QGwFvvMQCn", 45 | "CurseForge": "https://www.curseforge.com/minecraft/mc-mods/structurify", 46 | "Modrinth": "https://modrinth.com/mod/structurify" 47 | } 48 | }, 49 | "catalogue": { 50 | "configFactory": "com.faboslav.structurify.common.modcompat.fabric.CatalogueCompat", 51 | "icon": { 52 | "image": "catalogue_icon.png" 53 | }, 54 | "banner": "catalogue_logo.png", 55 | "background": "catalogue_background.png" 56 | }, 57 | "mc-publish": { 58 | "dependencies": [ 59 | "fabric-api(required){curseforge:306612}{modrinth:P7dR8mSH}", 60 | "yet_another_config_lib_v3(required){curseforge:667299}{modrinth:1eAoo2KR}", 61 | "modmenu(required){curseforge:308702}{modrinth:mOgUt4GM}" 62 | ] 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /fabric/src/main/resources/structurify-fabric.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "com.faboslav.structurify.fabric.mixin", 4 | "refmap": "${modId}.refmap.json", 5 | "compatibilityLevel": "JAVA_${javaVersion}", 6 | "minVersion": "0.8", 7 | "plugin": "com.faboslav.structurify.common.mixin.plugin.StructurifyMixinPlugin", 8 | "injectors": { 9 | "defaultRequire": 1 10 | }, 11 | "mixins": [ 12 | ] 13 | } -------------------------------------------------------------------------------- /forge/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `multiloader-loader` 3 | id("net.neoforged.moddev.legacyforge") 4 | id("dev.kikugie.j52j") version "2.0" 5 | } 6 | 7 | mixin { 8 | add(sourceSets.main.get(), "${mod.id}.refmap.json") 9 | 10 | config("${mod.id}-common.mixins.json") 11 | config("${mod.id}-forge.mixins.json") 12 | } 13 | 14 | legacyForge { 15 | enable { 16 | forgeVersion = "${mod.mc}-${commonMod.dep("forge")}" 17 | } 18 | } 19 | 20 | dependencies { 21 | compileOnly("org.jetbrains:annotations:24.1.0") 22 | annotationProcessor("org.spongepowered:mixin:0.8.5-SNAPSHOT:processor") 23 | 24 | "io.github.llamalad7:mixinextras-common:0.4.1".let { 25 | compileOnly(it) 26 | annotationProcessor(it) 27 | } 28 | 29 | "io.github.llamalad7:mixinextras-forge:0.4.1".let { 30 | implementation(it) 31 | jarJar(it) 32 | } 33 | 34 | // Required dependencies 35 | modImplementation("dev.isxander:yet-another-config-lib:${commonMod.dep("yacl")}-forge") 36 | 37 | // Global Packs 38 | commonMod.depOrNull("global_packs")?.let { globalPacksVersion -> 39 | modImplementation(commonMod.modrinth("globalpacks", "1.16.2_forge")) { isTransitive = false } 40 | } 41 | 42 | // Open Loader 43 | commonMod.depOrNull("open_loader")?.let { openLoaderVersion -> 44 | modImplementation( 45 | group = "net.darkhax.openloader", 46 | name = "OpenLoader-Forge-${commonMod.mc}", 47 | version = openLoaderVersion 48 | ) { isTransitive = false } 49 | } 50 | 51 | // Yungs Api 52 | commonMod.depOrNull("yungs_api_minecraft")?.let { yungsApiMcVersion -> 53 | commonMod.depOrNull("yungs_api")?.let { yungsApiVersion -> 54 | modImplementation("com.yungnickyoung.minecraft.yungsapi:YungsApi:$yungsApiMcVersion-Forge-$yungsApiVersion") { 55 | isTransitive = false 56 | } 57 | } 58 | } 59 | 60 | // Repurposed Structures 61 | commonMod.depOrNull("repurposed_structures")?.let { repurposedStructuresVersion -> 62 | modImplementation( 63 | commonMod.modrinth( 64 | "repurposed-structures-forge", 65 | "${repurposedStructuresVersion}-forge" 66 | ) 67 | ) { isTransitive = false } 68 | } 69 | 70 | // Structure Gel Api 71 | commonMod.depOrNull("structure_gel_api")?.let { structureGelApiVersion -> 72 | modImplementation(commonMod.modrinth("structure-gel-api", structureGelApiVersion)) { isTransitive = false } 73 | } 74 | 75 | // For debugging 76 | // modImplementation(modrinth("blue-skies", "1.3.31")) { transitive = false } 77 | } 78 | 79 | legacyForge { 80 | runs { 81 | register("client") { 82 | client() 83 | ideName = "Forge Client (${project.path})" 84 | } 85 | register("server") { 86 | server() 87 | ideName = "Forge Server (${project.path})" 88 | } 89 | } 90 | 91 | parchment { 92 | commonMod.depOrNull("parchment")?.let { 93 | mappingsVersion = it 94 | minecraftVersion = commonMod.mc 95 | } 96 | } 97 | 98 | mods { 99 | register(commonMod.id) { 100 | sourceSet(sourceSets.main.get()) 101 | } 102 | } 103 | } 104 | 105 | sourceSets.main { 106 | resources.srcDir("src/generated/resources") 107 | } 108 | 109 | tasks { 110 | jar { 111 | finalizedBy("reobfJar") 112 | manifest { 113 | attributes( 114 | mapOf( 115 | "MixinConfigs" to "${mod.id}-common.mixins.json,${mod.id}-forge.mixins.json" 116 | ) 117 | ) 118 | } 119 | } 120 | } -------------------------------------------------------------------------------- /forge/gradle.properties: -------------------------------------------------------------------------------- 1 | loader=forge -------------------------------------------------------------------------------- /forge/src/main/java/com/faboslav/structurify/forge/StructurifyForge.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.forge; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.commands.DumpCommand; 5 | import com.faboslav.structurify.common.events.common.LoadConfigEvent; 6 | import com.faboslav.structurify.common.events.common.UpdateRegistriesEvent; 7 | import com.faboslav.structurify.common.registry.StructurifyRegistryManagerProvider; 8 | import net.minecraftforge.api.distmarker.Dist; 9 | import net.minecraftforge.common.MinecraftForge; 10 | import net.minecraftforge.event.RegisterCommandsEvent; 11 | import net.minecraftforge.event.TagsUpdatedEvent; 12 | import net.minecraftforge.event.server.ServerAboutToStartEvent; 13 | import net.minecraftforge.eventbus.api.IEventBus; 14 | import net.minecraftforge.fml.common.Mod; 15 | import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; 16 | import net.minecraftforge.fml.loading.FMLEnvironment; 17 | 18 | @Mod(Structurify.MOD_ID) 19 | @SuppressWarnings("all") 20 | public final class StructurifyForge 21 | { 22 | public StructurifyForge() { 23 | IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); 24 | IEventBus eventBus = MinecraftForge.EVENT_BUS; 25 | 26 | Structurify.init(); 27 | 28 | if (FMLEnvironment.dist == Dist.CLIENT) { 29 | StructurifyForgeClient.init(modEventBus, eventBus); 30 | } 31 | 32 | eventBus.addListener(StructurifyForge::registerCommand); 33 | eventBus.addListener(StructurifyForge::onResourceManagerReload); 34 | eventBus.addListener(StructurifyForge::onServerAboutToStart); 35 | } 36 | 37 | private static void registerCommand(RegisterCommandsEvent event) { 38 | DumpCommand.createCommand(event.getDispatcher()); 39 | } 40 | 41 | private static void onResourceManagerReload(TagsUpdatedEvent event) { 42 | if (event.getUpdateCause() == TagsUpdatedEvent.UpdateCause.CLIENT_PACKET_RECEIVED) { 43 | return; 44 | } 45 | 46 | StructurifyRegistryManagerProvider.setRegistryManager(event.getRegistryAccess()); 47 | LoadConfigEvent.EVENT.invoke(new LoadConfigEvent()); 48 | } 49 | 50 | private static void onServerAboutToStart(ServerAboutToStartEvent event) { 51 | StructurifyRegistryManagerProvider.setRegistryManager(event.getServer().registryAccess()); 52 | UpdateRegistriesEvent.EVENT.invoke(new UpdateRegistriesEvent(event.getServer().registryAccess())); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /forge/src/main/java/com/faboslav/structurify/forge/StructurifyForgeClient.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.forge; 2 | 3 | import com.faboslav.structurify.common.StructurifyClient; 4 | import net.minecraftforge.api.distmarker.Dist; 5 | import net.minecraftforge.api.distmarker.OnlyIn; 6 | import net.minecraftforge.client.ConfigScreenHandler; 7 | import net.minecraftforge.eventbus.api.IEventBus; 8 | import net.minecraftforge.fml.ModLoadingContext; 9 | import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; 10 | 11 | @OnlyIn(Dist.CLIENT) 12 | @SuppressWarnings("all") 13 | public final class StructurifyForgeClient 14 | { 15 | public static void init(IEventBus modEventBus, IEventBus eventBus) { 16 | StructurifyClient.init(); 17 | 18 | modEventBus.addListener(StructurifyForgeClient::onClientSetup); 19 | } 20 | 21 | private static void onClientSetup(final FMLClientSetupEvent event) { 22 | event.enqueueWork(() -> { 23 | ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> 24 | new ConfigScreenHandler.ConfigScreenFactory( 25 | (mc, screen) -> StructurifyClient.getConfigScreen(screen) 26 | ) 27 | ); 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /forge/src/main/java/com/faboslav/structurify/forge/mixin/compat/StructureGelApiModifySpreadMixin.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.forge.mixin.compat; 2 | 3 | import com.faboslav.structurify.common.api.StructurifyRandomSpreadStructurePlacement; 4 | import com.faboslav.structurify.common.util.RandomSpreadUtil; 5 | import com.legacy.structure_gel.api.structure.GridStructurePlacement; 6 | import com.llamalad7.mixinextras.injector.ModifyReturnValue; 7 | import net.minecraft.resources.ResourceLocation; 8 | import org.jetbrains.annotations.Nullable; 9 | import org.spongepowered.asm.mixin.Final; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | 14 | @Mixin(value = GridStructurePlacement.class, remap = false) 15 | public abstract class StructureGelApiModifySpreadMixin implements StructurifyRandomSpreadStructurePlacement 16 | { 17 | @Shadow 18 | @Final 19 | private int spacing; 20 | 21 | @Shadow 22 | @Final 23 | private int offset; 24 | 25 | @Nullable 26 | public ResourceLocation structureSetIdentifier = null; 27 | 28 | @Shadow 29 | @Final 30 | public abstract int spacing(); 31 | 32 | @Shadow 33 | @Final 34 | public abstract int offset(); 35 | 36 | public void structurify$setStructureSetIdentifier(ResourceLocation structureSetIdentifier) { 37 | this.structureSetIdentifier = structureSetIdentifier; 38 | } 39 | 40 | @Nullable 41 | public ResourceLocation structurify$getStructureSetIdentifier() { 42 | return this.structureSetIdentifier; 43 | } 44 | 45 | public int structurify$getOriginalSpacing() { 46 | return this.spacing; 47 | } 48 | 49 | public int structurify$getOriginalSeparation() { 50 | return this.offset; 51 | } 52 | 53 | @ModifyReturnValue( 54 | method = "spacing", 55 | at = @At("RETURN") 56 | ) 57 | protected int structurify$getSpacing(int originalSpacing) { 58 | return RandomSpreadUtil.getModifiedSpacing(this.structurify$getStructureSetIdentifier(), originalSpacing); 59 | } 60 | 61 | @ModifyReturnValue( 62 | method = "offset", 63 | at = @At("RETURN") 64 | ) 65 | protected int structurify$getOffset(int originalOffset) { 66 | return RandomSpreadUtil.getModifiedSeparation(this.structurify$getStructureSetIdentifier(), this.spacing(), originalOffset); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /forge/src/main/java/com/faboslav/structurify/forge/platform/ForgePlatformCompat.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.forge.platform; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.platform.PlatformCompat; 5 | 6 | public final class ForgePlatformCompat implements PlatformCompat 7 | { 8 | @Override 9 | public void setupPlatformModCompat() { 10 | String modId = ""; 11 | 12 | try { 13 | } catch (Throwable e) { 14 | Structurify.getLogger().error("Failed to setup compat with " + modId); 15 | e.printStackTrace(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /forge/src/main/java/com/faboslav/structurify/forge/platform/ForgePlatformHelper.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.forge.platform; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.platform.PlatformHelper; 5 | import net.minecraftforge.fml.ModList; 6 | import net.minecraftforge.fml.loading.FMLPaths; 7 | 8 | import javax.annotation.Nullable; 9 | import java.nio.file.Path; 10 | 11 | public final class ForgePlatformHelper implements PlatformHelper 12 | { 13 | public boolean isModLoaded(String modId) { 14 | return ModList.get().isLoaded(modId); 15 | } 16 | 17 | @Override 18 | @Nullable 19 | public String getModVersion() { 20 | return ModList.get().getModContainerById(Structurify.MOD_ID).map(modContainer -> modContainer.getModInfo().getVersion().toString()).orElse(null); 21 | } 22 | 23 | @Override 24 | public Path getConfigDirectory() { 25 | return FMLPaths.CONFIGDIR.get(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /forge/src/main/java/com/faboslav/structurify/forge/platform/ForgePlatformResourcePackProvider.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.forge.platform; 2 | 3 | import com.faboslav.structurify.common.platform.PlatformResourcePackProvider; 4 | import net.minecraft.server.packs.repository.RepositorySource; 5 | 6 | import java.util.ArrayList; 7 | 8 | /** 9 | * Forge injects stuff into the vanilla registry 10 | */ 11 | public final class ForgePlatformResourcePackProvider implements PlatformResourcePackProvider 12 | { 13 | @Override 14 | public ArrayList getPlatformResourcePackProviders() { 15 | ArrayList platformResourcePackProviders = new ArrayList<>(); 16 | return platformResourcePackProviders; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/mods.toml: -------------------------------------------------------------------------------- 1 | modLoader = "javafml" 2 | loaderVersion = "*" 3 | license = "CC BY-NC-ND 4.0" 4 | issueTrackerURL = "https://github.com/Faboslav/structurify/issues" 5 | 6 | [[mods]] 7 | modId = "${modId}" 8 | version = "${modVersion}" 9 | displayName = "${modName}" 10 | authors = "${modAuthor}" 11 | description = "${modDescription}" 12 | logoFile = "icon.png" 13 | logoBlur = false 14 | displayURL = "https://www.curseforge.com/minecraft/mc-mods/structurify" 15 | 16 | [[mixins]] 17 | config = "structurify-common.mixins.json" 18 | 19 | [[mixins]] 20 | config = "structurify-forge.mixins.json" 21 | 22 | [[dependencies.${ modId }]] 23 | modId = "forge" 24 | mandatory = true 25 | versionRange = "*" 26 | ordering = "NONE" 27 | side = "BOTH" 28 | 29 | [[dependencies.${ modId }]] 30 | modId = "minecraft" 31 | mandatory = true 32 | versionRange = "[${minMinecraftVersion},)" 33 | ordering = "NONE" 34 | side = "BOTH" 35 | 36 | [[dependencies.${ modId }]] 37 | modId = "yet_another_config_lib_v3" 38 | mandatory = true 39 | versionRange = "[${yaclVersion},)" 40 | ordering = "NONE" 41 | side = "BOTH" 42 | [dependencies.${ modId }.mc-publish] 43 | ignore = false 44 | modrinth = "yacl" 45 | curseforge = "yacl" 46 | 47 | [modproperties.${ modId }] 48 | catalogueImageIcon = "catalogue_icon.png" 49 | catalogueBackground = "catalogue_background.png" 50 | configuredBackground = "catalogue_background.png" -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/services/com.faboslav.structurify.common.platform.PlatformCompat: -------------------------------------------------------------------------------- 1 | com.faboslav.structurify.forge.platform.ForgePlatformCompat -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/services/com.faboslav.structurify.common.platform.PlatformHelper: -------------------------------------------------------------------------------- 1 | com.faboslav.structurify.forge.platform.ForgePlatformHelper -------------------------------------------------------------------------------- /forge/src/main/resources/META-INF/services/com.faboslav.structurify.common.platform.PlatformResourcePackProvider: -------------------------------------------------------------------------------- 1 | com.faboslav.structurify.forge.platform.ForgePlatformResourcePackProvider -------------------------------------------------------------------------------- /forge/src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "Structurify", 4 | "forge:server_data_pack_format": 15, 5 | "pack_format": 15 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /forge/src/main/resources/structurify-forge.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "com.faboslav.structurify.forge.mixin", 4 | "refmap": "${modId}.refmap.json", 5 | "compatibilityLevel": "JAVA_${javaVersion}", 6 | "minVersion": "0.8", 7 | "plugin": "com.faboslav.structurify.common.mixin.plugin.StructurifyMixinPlugin", 8 | "injectors": { 9 | "defaultRequire": 1 10 | }, 11 | "mixins": [ 12 | "compat.StructureGelApiModifySpreadMixin" 13 | ] 14 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Dev 2 | org.gradle.jvmargs=-Xmx4G 3 | org.gradle.parallel=true 4 | org.gradle.caching=true 5 | org.gradle.configureondemand=false 6 | org.gradle.configuration-cache=false 7 | 8 | # Java 9 | java.version= 10 | 11 | # Mod 12 | mod.name=Structurify 13 | mod.id=structurify 14 | mod.group=com.faboslav.structurify 15 | mod.version=1.0.13 16 | mod.author=Faboslav 17 | mod.description=Configuration mod that makes configuring everything related to structures very easy and accessible, eliminating the hassle of creating multiple datapacks. 18 | mod.license=CC-BY-NC-ND-4.0 19 | mod.github_url=https://github.com/Faboslav/structurify 20 | mod.issue_tracker_url=https://github.com/Faboslav/structurify/issues 21 | mod.curseforge_url=https://www.curseforge.com/minecraft/mc-mods/structurify 22 | 23 | # Minecraft 24 | minecraft_version= 25 | min_minecraft_version= 26 | 27 | # Mappings 28 | deps.parchment= 29 | 30 | # Stonecutter 31 | stonecutter_enabled_platforms=fabric, neoforge, forge 32 | stonecutter_enabled_common_versions = 1.20.1, 1.21.1, 1.21.3, 1.21.4, 1.21.5 33 | stonecutter_enabled_fabric_versions = 1.20.1, 1.21.1, 1.21.3, 1.21.4, 1.21.5 34 | stonecutter_enabled_forge_versions = 1.20.1 35 | stonecutter_enabled_neoforge_versions = 1.21.1, 1.21.3, 1.21.4, 1.21.5 36 | 37 | # Fabric https://fabricmc.net/versions.html 38 | deps.fabric_loader= 39 | deps.fabric_api= 40 | 41 | # Forge https://files.minecraftforge.net/net/minecraftforge/forge 42 | deps.forge= 43 | 44 | # NeoForge https://projects.neoforged.net/neoforged/neoforge 45 | deps.neoforge= 46 | 47 | # Dependencies 48 | deps.yacl= 49 | deps.mod_menu= 50 | deps.catalogue= 51 | deps.global_datapacks= 52 | deps.global_packs= 53 | deps.open_loader= 54 | deps.yungs_api_minecraft= 55 | deps.yungs_api= 56 | deps.repurposed_structures= 57 | deps.structure_gel_api= 58 | deps.midnight_lib= 59 | deps.terra= -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Faboslav/structurify/aa0077e2d91d8ca890770184a8dc192d2cbd4c03/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributidistributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /neoforge/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `multiloader-loader` 3 | id("net.neoforged.moddev") 4 | id("dev.kikugie.j52j") version "2.0" 5 | } 6 | 7 | neoForge { 8 | enable { 9 | version = commonMod.dep("neoforge") 10 | } 11 | } 12 | 13 | dependencies { 14 | // Required dependencies 15 | implementation("dev.isxander:yet-another-config-lib:${commonMod.dep("yacl")}-neoforge") 16 | 17 | // Global Packs 18 | commonMod.depOrNull("global_packs")?.let { globalPacksVersion -> 19 | implementation(commonMod.modrinth("globalpacks", globalPacksVersion)) { isTransitive = false } 20 | } 21 | 22 | // Open Loader 23 | commonMod.depOrNull("open_loader")?.let { openLoaderVersion -> 24 | println("including") 25 | if (commonMod.mc == "1.21.1") { 26 | implementation( 27 | group = "net.darkhax.openloader", 28 | name = "openloader-neoforge-${commonMod.mc}", 29 | version = openLoaderVersion 30 | ) 31 | } else { 32 | implementation( 33 | group = "net.darkhax.openloader", 34 | name = "OpenLoader-NeoForge-${commonMod.mc}", 35 | version = openLoaderVersion 36 | ) 37 | } 38 | } 39 | 40 | // Yungs api 41 | commonMod.depOrNull("yungs_api_minecraft")?.let { yungsApiMcVersion -> 42 | commonMod.depOrNull("yungs_api")?.let { yungsApiVersion -> 43 | implementation("com.yungnickyoung.minecraft.yungsapi:YungsApi:$yungsApiMcVersion-NeoForge-$yungsApiVersion") { 44 | isTransitive = false 45 | } 46 | } 47 | } 48 | 49 | // Repurposed Structures 50 | commonMod.depOrNull("repurposed_structures")?.let { repurposedStructuresVersion -> 51 | implementation("com.telepathicgrunt:RepurposedStructures:${repurposedStructuresVersion}-neoforge") 52 | } 53 | } 54 | 55 | neoForge { 56 | runs { 57 | register("client") { 58 | client() 59 | ideName = "NeoForge Client (${project.path})" 60 | } 61 | register("server") { 62 | server() 63 | ideName = "NeoForge Server (${project.path})" 64 | } 65 | } 66 | 67 | parchment { 68 | commonMod.depOrNull("parchment")?.let { 69 | mappingsVersion = it 70 | minecraftVersion = commonMod.mc 71 | } 72 | } 73 | 74 | mods { 75 | register(commonMod.id) { 76 | sourceSet(sourceSets.main.get()) 77 | } 78 | } 79 | } 80 | 81 | sourceSets.main { 82 | resources.srcDir("src/generated/resources") 83 | } -------------------------------------------------------------------------------- /neoforge/gradle.properties: -------------------------------------------------------------------------------- 1 | loader=neoforge -------------------------------------------------------------------------------- /neoforge/src/main/java/com/faboslav/structurify/neoforge/StructurifyNeoForge.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.neoforge; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.commands.DumpCommand; 5 | import com.faboslav.structurify.common.events.common.LoadConfigEvent; 6 | import com.faboslav.structurify.common.events.common.UpdateRegistriesEvent; 7 | import com.faboslav.structurify.common.registry.StructurifyRegistryManagerProvider; 8 | import net.neoforged.api.distmarker.Dist; 9 | import net.neoforged.bus.api.IEventBus; 10 | import net.neoforged.fml.ModContainer; 11 | import net.neoforged.fml.common.Mod; 12 | import net.neoforged.fml.loading.FMLEnvironment; 13 | import net.neoforged.neoforge.common.NeoForge; 14 | import net.neoforged.neoforge.event.RegisterCommandsEvent; 15 | import net.neoforged.neoforge.event.TagsUpdatedEvent; 16 | import net.neoforged.neoforge.event.server.ServerAboutToStartEvent; 17 | 18 | @Mod(Structurify.MOD_ID) 19 | public final class StructurifyNeoForge 20 | { 21 | public StructurifyNeoForge(ModContainer modContainer, IEventBus modEventBus) { 22 | var eventBus = NeoForge.EVENT_BUS; 23 | 24 | Structurify.init(); 25 | 26 | if (FMLEnvironment.dist == Dist.CLIENT) { 27 | StructurifyNeoForgeClient.init(modEventBus, eventBus); 28 | } 29 | 30 | eventBus.addListener(StructurifyNeoForge::registerCommand); 31 | eventBus.addListener(StructurifyNeoForge::onResourceManagerReload); 32 | eventBus.addListener(StructurifyNeoForge::onServerAboutToStart); 33 | } 34 | 35 | private static void registerCommand(RegisterCommandsEvent event) { 36 | DumpCommand.createCommand(event.getDispatcher()); 37 | } 38 | 39 | private static void onResourceManagerReload(TagsUpdatedEvent event) { 40 | if (event.getUpdateCause() == TagsUpdatedEvent.UpdateCause.CLIENT_PACKET_RECEIVED) { 41 | return; 42 | } 43 | 44 | //? >=1.21.3 { 45 | var registryAccess = event.getLookupProvider(); 46 | //?} else { 47 | /*var registryAccess = event.getRegistryAccess(); 48 | *///?} 49 | 50 | StructurifyRegistryManagerProvider.setRegistryManager(registryAccess); 51 | LoadConfigEvent.EVENT.invoke(new LoadConfigEvent()); 52 | } 53 | 54 | private static void onServerAboutToStart(ServerAboutToStartEvent event) { 55 | StructurifyRegistryManagerProvider.setRegistryManager(event.getServer().registryAccess()); 56 | UpdateRegistriesEvent.EVENT.invoke(new UpdateRegistriesEvent(event.getServer().registryAccess())); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /neoforge/src/main/java/com/faboslav/structurify/neoforge/StructurifyNeoForgeClient.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.neoforge; 2 | 3 | import com.faboslav.structurify.common.StructurifyClient; 4 | import net.neoforged.api.distmarker.Dist; 5 | import net.neoforged.api.distmarker.OnlyIn; 6 | import net.neoforged.bus.api.IEventBus; 7 | import net.neoforged.fml.ModLoadingContext; 8 | import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; 9 | //? <1.20.6 { 10 | /*import net.neoforged.neoforge.client.ConfigScreenHandler; 11 | 12 | *///?} else { 13 | import net.neoforged.neoforge.client.gui.IConfigScreenFactory; 14 | //?} 15 | 16 | @OnlyIn(Dist.CLIENT) 17 | public final class StructurifyNeoForgeClient 18 | { 19 | public static void init(IEventBus modEventBus, IEventBus eventBus) { 20 | StructurifyClient.init(); 21 | 22 | modEventBus.addListener(StructurifyNeoForgeClient::onClientSetup); 23 | } 24 | 25 | private static void onClientSetup(final FMLClientSetupEvent event) { 26 | event.enqueueWork(() -> { 27 | //? <1.20.6 { 28 | /*ModLoadingContext.get().registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, () -> 29 | new ConfigScreenHandler.ConfigScreenFactory( 30 | (mc, screen) -> StructurifyClient.getConfigScreen(screen) 31 | ) 32 | ); 33 | *///?} else { 34 | ModLoadingContext.get().registerExtensionPoint(IConfigScreenFactory.class, () -> (client, screen) -> { 35 | return StructurifyClient.getConfigScreen(screen); 36 | }); 37 | //?} 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /neoforge/src/main/java/com/faboslav/structurify/neoforge/platform/NeoForgePlatformCompat.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.neoforge.platform; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.platform.PlatformCompat; 5 | 6 | public final class NeoForgePlatformCompat implements PlatformCompat 7 | { 8 | @Override 9 | public void setupPlatformModCompat() { 10 | String modId = ""; 11 | 12 | try { 13 | } catch (Throwable e) { 14 | Structurify.getLogger().error("Failed to setup compat with " + modId); 15 | e.printStackTrace(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /neoforge/src/main/java/com/faboslav/structurify/neoforge/platform/NeoForgePlatformHelper.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.neoforge.platform; 2 | 3 | import com.faboslav.structurify.common.Structurify; 4 | import com.faboslav.structurify.common.platform.PlatformHelper; 5 | import net.neoforged.fml.ModList; 6 | import net.neoforged.fml.loading.FMLPaths; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.nio.file.Path; 10 | 11 | public final class NeoForgePlatformHelper implements PlatformHelper 12 | { 13 | @Override 14 | public boolean isModLoaded(String modId) { 15 | return ModList.get().isLoaded(modId); 16 | } 17 | 18 | @Override 19 | @Nullable 20 | public String getModVersion() { 21 | return ModList.get().getModContainerById(Structurify.MOD_ID).map(modContainer -> modContainer.getModInfo().getVersion().toString()).orElse(null); 22 | } 23 | 24 | @Override 25 | public Path getConfigDirectory() { 26 | return FMLPaths.CONFIGDIR.get(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /neoforge/src/main/java/com/faboslav/structurify/neoforge/platform/NeoForgePlatformResourcePackProvider.java: -------------------------------------------------------------------------------- 1 | package com.faboslav.structurify.neoforge.platform; 2 | 3 | import com.faboslav.structurify.common.platform.PlatformResourcePackProvider; 4 | import net.minecraft.server.packs.repository.RepositorySource; 5 | 6 | import java.util.ArrayList; 7 | 8 | /** 9 | * NeoForge injects stuff into the vanilla registry 10 | */ 11 | public final class NeoForgePlatformResourcePackProvider implements PlatformResourcePackProvider 12 | { 13 | @Override 14 | public ArrayList getPlatformResourcePackProviders() { 15 | ArrayList platformResourcePackProviders = new ArrayList<>(); 16 | return platformResourcePackProviders; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /neoforge/src/main/resources/META-INF/neoforge.mods.toml: -------------------------------------------------------------------------------- 1 | modLoader = "javafml" 2 | loaderVersion = "*" 3 | license = "CC-BY-NC-ND-4.0" 4 | issueTrackerURL = "https://github.com/Faboslav/structurify/issues" 5 | 6 | [[mods]] 7 | modId = "${modId}" 8 | version = "${modVersion}" 9 | displayName = "${modName}" 10 | authors = "${modAuthor}" 11 | description = "${modDescription}" 12 | logoFile = "icon.png" 13 | logoBlur = false 14 | displayURL = "https://www.curseforge.com/minecraft/mc-mods/structurify" 15 | 16 | [[mixins]] 17 | config = "structurify-common.mixins.json" 18 | 19 | [[mixins]] 20 | config = "structurify-neoforge.mixins.json" 21 | 22 | [[dependencies.${ modId }]] 23 | modId = "neoforge" 24 | type = "required" 25 | versionRange = "*" 26 | ordering = "NONE" 27 | side = "BOTH" 28 | 29 | [[dependencies.${ modId }]] 30 | modId = "minecraft" 31 | type = "required" 32 | versionRange = "[${minMinecraftVersion},)" 33 | ordering = "NONE" 34 | side = "BOTH" 35 | 36 | [[dependencies.${ modId }]] 37 | modId = "yet_another_config_lib_v3" 38 | type = "required" 39 | versionRange = "[${yaclVersion},)" 40 | ordering = "NONE" 41 | side = "BOTH" 42 | [dependencies.${ modId }.mc-publish] 43 | ignore = false 44 | modrinth = "yacl" 45 | curseforge = "yacl" 46 | 47 | [modproperties.${ modId }] 48 | catalogueImageIcon = "catalogue_icon.png" 49 | catalogueBackground = "catalogue_background.png" 50 | configuredBackground = "catalogue_background.png" -------------------------------------------------------------------------------- /neoforge/src/main/resources/META-INF/services/com.faboslav.structurify.common.platform.PlatformCompat: -------------------------------------------------------------------------------- 1 | com.faboslav.structurify.neoforge.platform.NeoForgePlatformCompat -------------------------------------------------------------------------------- /neoforge/src/main/resources/META-INF/services/com.faboslav.structurify.common.platform.PlatformHelper: -------------------------------------------------------------------------------- 1 | com.faboslav.structurify.neoforge.platform.NeoForgePlatformHelper -------------------------------------------------------------------------------- /neoforge/src/main/resources/META-INF/services/com.faboslav.structurify.common.platform.PlatformResourcePackProvider: -------------------------------------------------------------------------------- 1 | com.faboslav.structurify.neoforge.platform.NeoForgePlatformResourcePackProvider -------------------------------------------------------------------------------- /neoforge/src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "Structurify", 4 | "pack_format": 8 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /neoforge/src/main/resources/structurify-neoforge.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "com.faboslav.structurify.neoforge.mixin", 4 | "refmap": "${modId}.refmap.json", 5 | "compatibilityLevel": "JAVA_${javaVersion}", 6 | "minVersion": "0.8", 7 | "plugin": "com.faboslav.structurify.common.mixin.plugin.StructurifyMixinPlugin", 8 | "injectors": { 9 | "defaultRequire": 1 10 | }, 11 | "mixins": [] 12 | } -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | mavenCentral() 5 | maven("https://maven.fabricmc.net/") 6 | maven("https://maven.neoforged.net/releases/") 7 | maven("https://maven.minecraftforge.net") 8 | maven("https://maven.kikugie.dev/snapshots") 9 | maven("https://maven.kikugie.dev/releases") 10 | } 11 | } 12 | 13 | plugins { 14 | id("dev.kikugie.stonecutter") version "0.6" 15 | id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" 16 | } 17 | 18 | val commonVersions = providers.gradleProperty("stonecutter_enabled_common_versions").orNull?.split(",")?.map { it.trim() } ?: emptyList() 19 | val fabricVersions = providers.gradleProperty("stonecutter_enabled_fabric_versions").orNull?.split(",")?.map { it.trim() } ?: emptyList() 20 | val forgeVersions = providers.gradleProperty("stonecutter_enabled_forge_versions").orNull?.split(",")?.map { it.trim() } ?: emptyList() 21 | val neoforgeVersions = providers.gradleProperty("stonecutter_enabled_neoforge_versions").orNull?.split(",")?.map { it.trim() } ?: emptyList() 22 | val dists = mapOf( 23 | "common" to commonVersions, 24 | "fabric" to fabricVersions, 25 | "forge" to forgeVersions, 26 | "neoforge" to neoforgeVersions 27 | ) 28 | val uniqueVersions = dists.values.flatten().distinct() 29 | 30 | stonecutter { 31 | kotlinController = true 32 | centralScript = "build.gradle.kts" 33 | 34 | create(rootProject) { 35 | versions(*uniqueVersions.toTypedArray()) 36 | 37 | dists.forEach { (branchName, branchVersions) -> 38 | branch(branchName) { 39 | versions(*branchVersions.toTypedArray()) 40 | } 41 | } 42 | } 43 | } 44 | 45 | rootProject.name = "structurify" 46 | 47 | -------------------------------------------------------------------------------- /stonecutter.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.kikugie.stonecutter.RunConfigType 2 | 3 | plugins { 4 | id("dev.kikugie.stonecutter") 5 | 6 | id("net.neoforged.moddev") version "2.0.78" apply false 7 | id("fabric-loom") version "1.10-SNAPSHOT" apply false 8 | } 9 | 10 | stonecutter active "1.21.5" /* [SC] DO NOT EDIT */ 11 | 12 | stonecutter registerChiseled tasks.register("chiseledBuild", stonecutter.chiseled) { 13 | group = mod.id 14 | ofTask("build") 15 | } 16 | 17 | stonecutter { 18 | generateRunConfigs = listOf(RunConfigType.SWITCH) 19 | } -------------------------------------------------------------------------------- /versions/1.20.1/gradle.properties: -------------------------------------------------------------------------------- 1 | # Stonecutter 2 | stonecutter_enabled_platforms=fabric, forge 3 | 4 | # Java 5 | java.version=17 6 | 7 | # Minecraft 8 | minecraft_version=1.20.1 9 | min_minecraft_version=1.20 10 | 11 | # Mappings 12 | deps.parchment=2023.09.03 13 | 14 | # Fabric 15 | deps.fabric_loader=0.16.0 16 | deps.fabric_api=0.92.1 17 | 18 | # Forge 19 | deps.forge=47.4.0 20 | 21 | # NeoForge 22 | deps.neoforge= 23 | 24 | # Dependencies 25 | deps.yacl=3.6.6+1.20.1 26 | deps.mod_menu=7.2.2 27 | deps.catalogue=1.8.0 28 | deps.global_datapacks=1.2 29 | deps.global_packs=1.16.1 30 | deps.open_loader=19.0.4 31 | deps.yungs_api_minecraft=1.20 32 | deps.yungs_api=4.0.1 33 | deps.repurposed_structures=7.1.15+1.20.1 34 | deps.structure_gel_api=2.16.2 35 | deps.midnight_lib=1.4.1 36 | deps.terra=6.3.1-BETA+6fa97d2ff -------------------------------------------------------------------------------- /versions/1.21.1/gradle.properties: -------------------------------------------------------------------------------- 1 | # Stonecutter 2 | stonecutter_enabled_platforms=fabric, neoforge 3 | 4 | # Java 5 | java.version=21 6 | 7 | # Minecraft 8 | minecraft_version=1.21.1 9 | min_minecraft_version=1.21 10 | 11 | # Mappings 12 | deps.parchment=2024.11.17 13 | 14 | # Fabric 15 | deps.fabric_loader=0.16.10 16 | deps.fabric_api=0.115.1 17 | 18 | # NeoForge 19 | deps.neoforge=21.1.138 20 | 21 | # Dependencies 22 | deps.yacl=3.6.6+1.21.1 23 | deps.mod_menu=11.0.1 24 | deps.catalogue=1.9.1 25 | deps.global_datapacks=1.4 26 | deps.global_packs=21.0.0 27 | deps.open_loader=21.1.5 28 | deps.yungs_api_minecraft=1.21 29 | deps.yungs_api=5.0.0 30 | deps.repurposed_structures=7.5.6+1.21.1 31 | deps.structure_gel_api= 32 | deps.midnight_lib=1.5.7 33 | deps.terra=6.5.1-BETA+0a952cff4 -------------------------------------------------------------------------------- /versions/1.21.3/gradle.properties: -------------------------------------------------------------------------------- 1 | # Stonecutter 2 | stonecutter_enabled_platforms=fabric, neoforge 3 | 4 | # Java 5 | java.version=21 6 | 7 | # Minecraft 8 | minecraft_version=1.21.3 9 | min_minecraft_version=1.21.2 10 | 11 | # Mappings 12 | deps.parchment=2024.12.07 13 | 14 | # Fabric 15 | deps.fabric_loader=0.16.10 16 | deps.fabric_api=0.114.0 17 | 18 | # NeoForge 19 | deps.neoforge=21.3.64 20 | 21 | # Dependencies 22 | deps.yacl=3.6.6+1.21.3 23 | deps.mod_menu=12.0.0-beta.1 24 | deps.catalogue=1.9.1 25 | deps.global_datapacks=1.5 26 | deps.global_packs= 27 | deps.open_loader= 28 | deps.yungs_api_minecraft= 29 | deps.yungs_api= 30 | deps.repurposed_structures= 31 | deps.structure_gel_api= 32 | deps.midnight_lib= 33 | deps.terra= -------------------------------------------------------------------------------- /versions/1.21.4/gradle.properties: -------------------------------------------------------------------------------- 1 | # Stonecutter 2 | stonecutter_enabled_platforms=fabric, neoforge 3 | 4 | # Java 5 | java.version=21 6 | 7 | # Minecraft 8 | minecraft_version=1.21.4 9 | min_minecraft_version=1.21.4 10 | 11 | # Mappings 12 | deps.parchment=2025.02.16 13 | 14 | # Fabric 15 | deps.fabric_loader=0.16.10 16 | deps.fabric_api=0.118.0 17 | 18 | # Neoforge 19 | deps.neoforge=21.4.123 20 | 21 | # Dependencies 22 | deps.yacl=3.6.5+1.21.4 23 | deps.mod_menu=13.0.2 24 | deps.catalogue=1.9.1 25 | deps.global_datapacks=1.5 26 | deps.global_packs= 27 | deps.open_loader= 28 | deps.yungs_api_minecraft=1.21.4 29 | deps.yungs_api=5.4.0 30 | deps.repurposed_structures=7.5.16+1.21.4 31 | deps.structure_gel_api= 32 | deps.midnight_lib=1.5.7 33 | deps.terra=6.6.1-BETA+1d658bd52 -------------------------------------------------------------------------------- /versions/1.21.5/gradle.properties: -------------------------------------------------------------------------------- 1 | # Stonecutter 2 | stonecutter_enabled_platforms=fabric, neoforge 3 | 4 | # Java 5 | java.version=21 6 | 7 | # Minecraft 8 | minecraft_version=1.21.5 9 | min_minecraft_version=1.21.5 10 | 11 | # Mappings 12 | deps.parchment=2025.04.19 13 | 14 | # Fabric 15 | deps.fabric_loader=0.16.10 16 | deps.fabric_api=0.119.6 17 | 18 | # Neoforge 19 | deps.neoforge=21.5.58-beta 20 | 21 | # Dependencies 22 | deps.yacl=3.6.6+1.21.5 23 | deps.mod_menu=14.0.0-rc.2 24 | deps.catalogue= 25 | deps.global_datapacks=1.6 26 | deps.global_packs= 27 | deps.open_loader= 28 | deps.yungs_api_minecraft= 29 | deps.yungs_api= 30 | deps.repurposed_structures=7.5.19+1.21.5 31 | deps.structure_gel_api= 32 | deps.midnight_lib=1.5.7 33 | deps.terra= --------------------------------------------------------------------------------