├── .github └── workflows │ └── build.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── readmes ├── READMEru.md ├── READMEtr.md ├── READMEuk.md └── READMEzh.md ├── settings.gradle ├── src └── main │ ├── java │ └── kaptainwutax │ │ └── seedcrackerX │ │ ├── Features.java │ │ ├── SeedCracker.java │ │ ├── api │ │ └── SeedCrackerAPI.java │ │ ├── command │ │ ├── ClientCommand.java │ │ ├── CrackerCommand.java │ │ ├── DataCommand.java │ │ ├── DatabaseCommand.java │ │ ├── FinderCommand.java │ │ ├── GuiCommand.java │ │ ├── RenderCommand.java │ │ └── VersionCommand.java │ │ ├── config │ │ ├── Config.java │ │ ├── ConfigScreen.java │ │ ├── ScModMenuEntry.java │ │ └── StructureSave.java │ │ ├── cracker │ │ ├── BiomeData.java │ │ ├── DataAddedEvent.java │ │ ├── HashedSeedData.java │ │ ├── PillarData.java │ │ ├── decorator │ │ │ ├── Decorator.java │ │ │ ├── DeepDungeon.java │ │ │ ├── Dungeon.java │ │ │ ├── EmeraldOre.java │ │ │ ├── FullFungusData.java │ │ │ └── WarpedFungus.java │ │ └── storage │ │ │ ├── DataStorage.java │ │ │ ├── ProgressListener.java │ │ │ ├── ScheduledSet.java │ │ │ └── TimeMachine.java │ │ ├── finder │ │ ├── BiomeFinder.java │ │ ├── BlockFinder.java │ │ ├── BlockUpdateQueue.java │ │ ├── Finder.java │ │ ├── FinderBuilder.java │ │ ├── FinderControl.java │ │ ├── FinderQueue.java │ │ ├── ReloadFinders.java │ │ ├── decorator │ │ │ ├── DesertWellFinder.java │ │ │ ├── DungeonFinder.java │ │ │ ├── EndGatewayFinder.java │ │ │ ├── EndPillarsFinder.java │ │ │ ├── WarpedFungusFinder.java │ │ │ └── ore │ │ │ │ └── EmeraldOreFinder.java │ │ └── structure │ │ │ ├── AbstractTempleFinder.java │ │ │ ├── BuriedTreasureFinder.java │ │ │ ├── DesertPyramidFinder.java │ │ │ ├── EndCityFinder.java │ │ │ ├── IglooFinder.java │ │ │ ├── JigsawFinder.java │ │ │ ├── JunglePyramidFinder.java │ │ │ ├── MonumentFinder.java │ │ │ ├── OutpostFinder.java │ │ │ ├── PieceFinder.java │ │ │ ├── ShipwreckFinder.java │ │ │ └── SwampHutFinder.java │ │ ├── init │ │ └── ClientCommands.java │ │ ├── mixin │ │ ├── ClientPlayNetworkHandlerMixin.java │ │ ├── ClientPlayerEntityMixin.java │ │ └── ClientWorldMixin.java │ │ ├── render │ │ ├── Color.java │ │ ├── Cube.java │ │ ├── Cuboid.java │ │ ├── Line.java │ │ └── Renderer.java │ │ └── util │ │ ├── BiomeFixer.java │ │ ├── Database.java │ │ ├── FeatureToggle.java │ │ ├── HeightContext.java │ │ ├── Log.java │ │ ├── PosIterator.java │ │ └── Predicates.java │ └── resources │ ├── assets │ └── seedcrackerx │ │ ├── icon.png │ │ ├── lang │ │ ├── en_us.json │ │ ├── hi_in.json │ │ ├── ru_ru.json │ │ ├── tr_tr.json │ │ └── zh_cn.json │ │ └── shaders │ │ └── core │ │ └── rendertype_lines.fsh │ ├── fabric.mod.json │ └── seedcracker.mixins.json ├── taskBuild.bat └── taskSetup.bat /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Gradle 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle 3 | 4 | name: Build 5 | 6 | on: 7 | push: 8 | paths-ignore: 9 | - 'readmes/*' 10 | - '*.md' 11 | pull_request: 12 | workflow_dispatch: 13 | 14 | jobs: 15 | build: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Set up JDK 21 20 | uses: actions/setup-java@v2 21 | with: 22 | java-version: 21 23 | distribution: 'zulu' 24 | - name: Grant execute permission for gradlew 25 | run: chmod +x gradlew 26 | 27 | - name: Build with Gradle 28 | run: | 29 | ./gradlew build 30 | 31 | - name: Upload Artifact 32 | uses: actions/upload-artifact@v4 33 | if: github.ref != format('refs/heads/{0}', github.event.repository.default_branch) # Only runs if this CI was NOT triggered by the default branch 34 | with: 35 | name: build 36 | path: build/libs/* 37 | 38 | - name: Remove *-dev.jar 39 | if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch) # Only runs if this CI was triggered by the default branch 40 | run: rm ./build/libs/*-dev.jar || true 41 | - name: Remove *-api.jar 42 | if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch) # Only runs if this CI was triggered by the default branch 43 | run: rm ./build/libs/*-api.jar || true 44 | - name: Create prerelease 45 | if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch) # Only runs if this CI was triggered by the default branch 46 | uses: "marvinpinto/action-automatic-releases@latest" 47 | with: 48 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 49 | automatic_release_tag: "prerelease" 50 | prerelease: true 51 | title: "Prerelease Build" 52 | files: | 53 | ./build/libs/*.jar 54 | 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # gradle 2 | 3 | .gradle/ 4 | build/ 5 | out/ 6 | classes/ 7 | 8 | # idea 9 | 10 | .idea/ 11 | *.iml 12 | *.ipr 13 | *.iws 14 | 15 | # vscode 16 | 17 | .settings/ 18 | .vscode/ 19 | bin/ 20 | .classpath 21 | .project 22 | 23 | # fabric 24 | 25 | run/ 26 | logs/ 27 | 28 | src/main/java/kaptainwutax/stronghold/ 29 | 30 | credentials.properties 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 KaptainWutax 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | import net.fabricmc.loom.task.prod.ClientProductionRunTask 2 | 3 | plugins { 4 | id 'fabric-loom' version "${loom_version}" 5 | } 6 | 7 | base { 8 | archivesName = project.archives_base_name 9 | version = project.mod_version 10 | group = project.maven_group 11 | } 12 | 13 | repositories { 14 | maven { url "https://maven.terraformersmc.com/releases" } 15 | maven { url "https://maven.shedaniel.me/" } 16 | maven { url "https://maven.latticg.com/" } 17 | maven { url "https://maven.seedfinding.com/" } 18 | maven { url "https://maven-snapshots.seedfinding.com/" } 19 | maven { url "https://jitpack.io" } 20 | maven { url "https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1" } 21 | } 22 | 23 | dependencies { 24 | //to change the versions see the gradle.properties file 25 | minecraft "com.mojang:minecraft:${project.minecraft_version}" 26 | mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" 27 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" 28 | modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" 29 | 30 | include modImplementation(fabricApi.module("fabric-api-base", project.fabric_api_version)) 31 | include modImplementation(fabricApi.module("fabric-transitive-access-wideners-v1", project.fabric_api_version)) 32 | include modImplementation(fabricApi.module("fabric-command-api-v2", project.fabric_api_version)) 33 | include modImplementation(fabricApi.module("fabric-rendering-v1", project.fabric_api_version)) 34 | include modImplementation(fabricApi.module("fabric-resource-loader-v0", project.fabric_api_version)) 35 | 36 | modApi("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config_version}") { 37 | exclude(group: "net.fabricmc.fabric-api") 38 | } 39 | include("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config_version}") 40 | 41 | modImplementation ("com.terraformersmc:modmenu:${project.modmenu_version}") {transitive = false} 42 | 43 | include implementation("com.seedfinding:mc_math:${project.seedfinding_math_version}") { transitive = false } 44 | include implementation("com.seedfinding:mc_seed:${project.seedfinding_seed_version}") { transitive = false } 45 | include implementation("com.seedfinding:mc_core:${project.seedfinding_core_version}") { transitive = false } 46 | include implementation("com.seedfinding:mc_noise:${project.seedfinding_noise_version}") { transitive = false } 47 | include implementation("com.seedfinding:mc_biome:${project.seedfinding_biome_version}") { transitive = false } 48 | include implementation("com.seedfinding:mc_terrain:${project.seedfinding_terrain_version}") { transitive = false } 49 | include implementation("com.seedfinding:mc_feature:${project.seedfinding_feature_version}") { transitive = false } 50 | include implementation("com.seedfinding:mc_reversal:${project.seedfinding_reversal_version}") { transitive = false } 51 | 52 | include implementation("com.seedfinding:latticg:${project.latticg_version}") 53 | 54 | modRuntimeOnly("me.djtheredstoner:DevAuth-fabric:${project.devauth_version}") { 55 | exclude group: 'net.fabricmc', module: 'fabric-loader' 56 | } 57 | productionRuntimeMods("me.djtheredstoner:DevAuth-fabric:${project.devauth_version}") { 58 | exclude group: 'net.fabricmc', module: 'fabric-loader' 59 | } 60 | } 61 | 62 | processResources { 63 | def props = [version: project.version, loader_version: project.loader_version] 64 | inputs.properties props 65 | filteringCharset "UTF-8" 66 | 67 | filesMatching("fabric.mod.json") { 68 | expand props 69 | } 70 | 71 | from("LICENSE") { 72 | rename {"${it}_${project.base.archivesName.get()}"} 73 | } 74 | } 75 | 76 | tasks.register("prodClient", ClientProductionRunTask) { 77 | runDir = file("run") 78 | 79 | jvmArgs.add("-Ddevauth.enabled=true") 80 | 81 | javaLauncher = javaToolchains.launcherFor { 82 | languageVersion = JavaLanguageVersion.of(21) 83 | } 84 | } 85 | 86 | tasks.withType(JavaCompile).configureEach { 87 | it.options.release = 21 88 | } 89 | 90 | java { 91 | sourceCompatibility = JavaVersion.VERSION_21 92 | targetCompatibility = JavaVersion.VERSION_21 93 | } 94 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Done to increase the memory available to gradle. 2 | org.gradle.jvmargs=-Xmx2G 3 | 4 | # Fabric Properties 5 | # check these on https://fabricmc.net/develop/ 6 | minecraft_version=1.21.5 7 | yarn_mappings=1.21.5+build.1 8 | loader_version=0.16.10 9 | loom_version=1.10-SNAPSHOT 10 | 11 | # Mod Properties 12 | mod_version=2.15.3 13 | maven_group=kaptainwutax 14 | archives_base_name=seedcrackerX 15 | 16 | # Dependencies 17 | fabric_api_version=0.119.6+1.21.5 18 | modmenu_version=14.0.0-rc.2 19 | cloth_config_version=18.0.145 20 | 21 | seedfinding_math_version=851e9d0577dfdca50154e98f1d334bd31c641326 22 | seedfinding_seed_version=55f6242001f7eb4226df4ed0d023f1838a54a99d 23 | seedfinding_core_version=b84ff1c38be399eda096dbde2819258c62f81275 24 | seedfinding_noise_version=dbab3996ea3abff5dd420db53c31d5498afd2fe5 25 | seedfinding_biome_version=17af8cb1110fdc983b7cb2b887d1fb2060e23ee3 26 | seedfinding_terrain_version=a03e440ec5b282e399382f2cc5ad0db91b438d2e 27 | seedfinding_feature_version=755d3611ac1c499c28289ccca5b738af6a5859b7 28 | seedfinding_reversal_version=75aa6ce47a9f53a1aa212765e9830e08f6c86299 29 | 30 | latticg_version=1.07 31 | 32 | devauth_version=1.2.1 33 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/19MisterX98/SeedcrackerX/5b599dc241ea059f8ed2ce7f25414fed9db2b56b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-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 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | # Tell Jitpack to build using Java 21 (defaults to 8) 2 | before_install: 3 | # Fix: https://github.com/jitpack/jitpack.io/issues/4506#issuecomment-864562270 4 | - source "$HOME/.sdkman/bin/sdkman-init.sh" 5 | - sdk update 6 | - sdk install java 21.0.3-zulu 7 | - sdk use java 21.0.3-zulu 8 | -------------------------------------------------------------------------------- /readmes/READMEtr.md: -------------------------------------------------------------------------------- 1 | # SeedCrackerX [![Tüm Github Sürümleri](https://img.shields.io/github/downloads/19MisterX98/SeedCrackerX/total.svg)] 2 | 3 | ## Readme dili 4 | 5 | [中文](READMEzh.md) 6 | [Русский](READMEru.md) 7 | [Türkçe](./READMEtr.md) 8 | 9 | ## Bana ulaşın: 10 | 11 | - [Discord Sunucum](https://discord.gg/JRmHzqQYfp) 12 | - [Youtube](https://www.youtube.com/channel/UCby9ZxEjJCqmccQGF3GSYlA) 13 | 14 | ## Kurulum 15 | 16 | [Fabric mod yükleyicisi](https://fabricmc.net/use/)'ni indirip kurun 17 | 18 | SeedCrackerX'in son [sürümünü yada ön-sürümünü](https://github.com/19MisterX98/SeedCrackerX/releases) indirin 19 | 20 | .jar dosyalarını mod klasörünüze koyun, Vanilla Başlatıcı'sı için %appdata%/.minecraft/mods/ klasörü yada kendi MultiMC profilinizin konumu. 21 | 22 | #### İsteğe bağlı 23 | 24 | Daha düşük Minecraft sürümündeki sunuculara katılmak için [Multiconnect](https://github.com/Earthcomputer/multiconnect/releases) yada [ViaFabric](https://modrinth.com/mod/viafabric)'in son sürümünü indirin 25 | 26 | ## Veri tabanı 27 | 28 | Bu mod birçok insan tarafından kullanılması sebebiyle sunucu seed'leri için Google e-tablo'su açmaya karar verdim. 29 | Eğer konfigürasyon arayüzünden veri tabanı ayarını açarsanız mod, 10+ oyunculu sunucu seed'lerini Google e-tablo'suna yollayacak. 30 | Bunun için lisanslı bir minecraft'a sahip olmanız lazım 31 | 32 | [e-tablo](https://docs.google.com/spreadsheets/d/1tuQiE-0leW88em9OHbZnH-RFNhVqgoHhIt9WQbeqqWw/edit?usp=sharing) 33 | 34 | ## Kullanım 35 | 36 | ### 1.17.X ve alt sürümleri 37 | 38 | Mod zindan bulana kadar dünyada koşun. Mod 1 tane zindan bulduktan sonra seed bulma işlemini otomatik olarak başlatacak. 39 | Eğer mod, dünya seed'i bulamazsa başka bir zindan aramanız gerekebilir. 40 | 41 | Bu mod ayrıca şunlar ile seed bulabilir: 42 | - [Yapılar ve End Kuleleri](https://youtu.be/aUuPSZVPH8E?t=462) 43 | - [Eğri Mantar](https://youtu.be/HKjwgofhKs4) 44 | 45 | ### 1.18.X ve üst sürümleri 46 | 47 | Zindan ve mantarlar ile seed bulma işlemi artık çalışmıyor. 48 | 49 | Güncel olmadıkları ve yanlış veri verebilecekleri için "/seed gui" komudu aracılığıyla konfigürasyon menüsüne gidin ve Zümrütlerin, Geçitlerin, Biyomların, Çöl kuyularının ve Eğri Mantarların kapalı olduğuna emin olun 50 | 51 | Bulma işlemi için artık aşağıdaki 5 yapıdan bulmanız gerekir: 52 | Çöl Piramitleri, Orman Tapınakları, Cadı Kulübeleri, Gemi Enkazları, İglolar, Pillager Mıntıkaları 53 | 54 | Bunların herhangi bir kombinasyonu yeterli. Örnek olarak: 3 Gemi Enkazı, 1 Piramit ve 1 İglo 55 | Şu anki ilerlemenizi "/seed data bits" komudu aracılığıyla görebilirsiniz (Kaldırılabilir yapılar'ın bit sayılarına bakın) 56 | Bir yapı, etrafında dış çizgiler oluştuğunda bulunmuş olur. 57 | Yeterli veri topladıktan sonra, bulma işlemi otomatik olarak başlar. Bu işlem 1 ile 5 dakika arası sürer. 58 | 59 | Bu işlemden sonra mod fazladan yapı bulmanızı isteyebilir. 60 | Az bit'ler ile yada aynı tür yapılar ile bunun gerçekleşmesi daha muhtemeldir. 61 | Yapı seed'lerinizi azalttıktan sonra mod, brute force (kaba kuvvet) işlemi aracılığıyla dünyanızın seed'ini zindan konumları yada hash'lanmış seed ile bulacak. 62 | 63 | ### Desteği Olan Yapılar 64 | - Okyanus Mabetleri 65 | - End Şehirleri 66 | - Gömülü Hazineler 67 | - Çöl Piramitleri 68 | - Orman Tapınakları 69 | - Bataklık Kulübeleri 70 | - Gemi Enkazları 71 | - İglolar 72 | - Pillater Mıntıkaları 73 | 74 | ### Desteği Olan Dekoratörler 75 | - Zindanlar 76 | - End Geçitleri 77 | - Çöl Kuyuları 78 | - Zümrüt Cevherleri 79 | - Eğri Mantarlar 80 | 81 | ## Komutlar 82 | 83 | 1.19.3 sürümü için şu komutu kullanın 84 | - `/seedcracker` 85 | 86 | ### GUI (Kullanıcı Arayüzü) Komutu 87 | - `/seed gui` 88 | 89 | Minecraft Sürümünüz, tüm arayıcılar, veri tabanları ve render modunuzu değiştirebileceğiniz bir konfigürasyon gui'ı açar 90 | Bunların çoğunun komut alternatifleri var, fakat artık kullanılmamalılar. 91 | 92 | ### Bulucu'yu Yenileme Komutu 93 | - `/seed finder reload` 94 | 95 | Yüklü Chunk'ları daha önceden bulunamayan yapıları bulmak için tekrar tarar. 96 | 97 | ### Veri Komutu 98 | - `/seed data clear` 99 | 100 | Tekrar giriş istemeden toplanan tüm verileri temizler. Çok dünyalı sunucular için kullanışlı bir komut. 101 | 102 | - `/seed data bits` 103 | 104 | Kaç bit verinin toplandığını gösterir. 105 | Normal bit'ler End Kuleleri ve Yapılar ile bulma işleminde kullanılır. Bulma işlemi 32 bit'te başlar. 106 | Kaldırılabilir bit'ler kaldırılabilir yapılar ile bulma işleminde kullanılır. Bulma işlemi 40 bit'te başlar. 107 | 108 | - `/seed data restore` 109 | 110 | Bir dünyadan ayrıldığınızda mod; otomatik olarak, toplanan yapı bilgilerini bir dosyaya kaydeder (.minecraft/config) 111 | Tekrar katıldığınızda bu komut ile verileri kurtarabilirsiniz. 112 | 113 | ### Debug (hata ayıklama) Komutu 114 | 115 | - `/seed cracker debug` 116 | 117 | Detaylı bilgi gösterir 118 | 119 | ### Veri Tabanı Komutu 120 | - `/seed database` 121 | 122 | Mod tarafından yönetilen bir [google e-tablo'su](https://docs.google.com/spreadsheets/d/1tuQiE-0leW88em9OHbZnH-RFNhVqgoHhIt9WQbeqqWw/edit?usp=sharing) açar 123 | 124 | ## Video'lu Anlatımlar 125 | 126 | Neil'ın: 127 | - [1.15](https://youtu.be/1ChmLi9og8Q) 128 | - [1.16](https://youtu.be/aUuPSZVPH8E) 129 | 130 | 131 | Dyiing'in 132 | - [1.18](https://www.youtube.com/watch?v=tKeEyx7jIE4) 133 | 134 | 135 | Proje Sahibinin: 136 | - [Zindan ve End Kuleleri ile bulma](https://youtu.be/8ytfZ2MXosY) 137 | - [Nether ile bulma](https://youtu.be/HKjwgofhKs4) 138 | - [Yapı ile bulma](https://youtu.be/UXVrBaOR8H0) 139 | 140 | ## -- DEVAMI MOD GELİŞTİRİCİLERİ İÇİN -- 141 | 142 | ## Workspace'i hazırlayın 143 | 144 | -repository'i klonlayın. 145 | 146 | -`gradlew genSources ` komutunu terminal'de çalıştırın. 147 | 148 | ## Modu inşa edin 149 | 150 | -Versionu `build.gradle` ve `fabric.mod.json` dosyanarında güncelleyin. 151 | 152 | -`gradlew build` komutunu terminal'de çalıştırın. 153 | 154 | ## Diğer modlar için API 155 | 156 | - seedcracker-api ve jitpack'i build.gradle dosyasında dahil edin 157 | 158 | repositories { 159 | mavenCentral() 160 | maven { url "https://jitpack.io" } 161 | } 162 | 163 | dependencies { 164 | implementation (include('com.github.19MisterX98.SeedcrackerX:seedcrackerx-api:master-SNAPSHOT')) {transitive = false} 165 | } 166 | 167 | - API interface'ini implement'leyen bir class oluşturun 168 | 169 | package misterx.myMod.seedManagemnet.SeedCrackerEP 170 | 171 | import kaptainwutax.seedcrackerX.api.SeedCrackerAPI; 172 | 173 | public class SeedCrackerEP implements SeedCrackerAPI { 174 | @Override 175 | public void pushWorldSeed(long seed) { 176 | //do something 177 | Foo.bar(seed) 178 | } 179 | } 180 | 181 | - fabric.mod.json 'a entrypoint'inizin nerede olduğunu yazın 182 | 183 | "entrypoints": { 184 | "main": [...], 185 | "client": [...], 186 | "server": [...], 187 | "seedcrackerx": [ 188 | "misterx.myMod.seedManagemnet.SeedCrackerEP" 189 | ] 190 | }, 191 | 192 | ## Katkıda Bulunanlar 193 | 194 | [KaptainWutax](https://github.com/KaptainWutax) - Yazar 195 | 196 | [neil](https://www.youtube.com/watch?v=aUuPSZVPH8E) - Video'lu Anlatım 197 | 198 | [Nekzuris](https://github.com/Nekzuris) - README dosyası 199 | 200 | [19MisterX98](https://www.youtube.com/channel/UCby9ZxEjJCqmccQGF3GSYlA) - Bu fork'un yazarı 201 | 202 | [phasenull](https://github.com/phasenull) - Türkçe README ve dil desteği 203 | -------------------------------------------------------------------------------- /readmes/READMEuk.md: -------------------------------------------------------------------------------- 1 | # SeedCrackerX [![Github All Releases](https://img.shields.io/github/downloads/19MisterX98/SeedCrackerX/total.svg)] 2 | 3 | ## Мої активності: 4 | 5 | - [Мій Discord](https://discord.gg/JRmHzqQYfp) 6 | - [Youtube](https://www.youtube.com/channel/UCby9ZxEjJCqmccQGF3GSYlA) 7 | 8 | ## Встановлення 9 | 10 | Завантажте та встановіть [fabric](https://fabricmc.net/use/) 11 | 12 | Завантажте найновіший [реліз або пре-реліз](https://github.com/19MisterX98/SeedCrackerX/releases) SeedCrackerX 13 | 14 | перемістіть .jar файли в вашу папку з модами, або у папку %appdata%/.minecraft/mods/ для офіційного лаунчера або в вашу папку MultiMC. 15 | 16 | #### Опціональне 17 | 18 | Завантажте останній реліз [Multiconnect](https://github.com/Earthcomputer/multiconnect/releases) або [ViaFabric](https://modrinth.com/mod/viafabric), щоб підключатися до серверів на старіших версіях Майнкрафт. 19 | 20 | ## База даних 21 | 22 | Через те що мод використовується багатьма людьми, я створив Google таблицю для сідів серверів. 23 | Якщо ви ввімкнете опцію бази даних в графічних налаштуваннях моду, то він відправлятиме знайденні сіди з серверів з 10+ гравцями. 24 | Вам також буде потрібна ліцензія Майнкрафт. 25 | 26 | [Таблиця](https://docs.google.com/spreadsheets/d/1tuQiE-0leW88em9OHbZnH-RFNhVqgoHhIt9WQbeqqWw/edit?usp=sharing) 27 | 28 | ## Використання 29 | 30 | ### 1.17.X та нижче 31 | 32 | Побігайте по мапі поки ви не знайдете спавнер. Після того як мод побачив цей спавнер, процес знаходження сіда почнеться автоматично. 33 | Якщо мод не дасть сід, то ви маєте знайти ще один спавнер. 34 | 35 | Також мод підтримую знаходження сіда через: 36 | - [Структури й вежі краю](https://youtu.be/aUuPSZVPH8E?t=462) 37 | - [Скажені гриби](https://youtu.be/HKjwgofhKs4) 38 | 39 | ### 1.18.X та вище 40 | 41 | Знаходження за допомогою спавнерів та скажених грибів більше не працює. 42 | 43 | Зайдіть в налаштування за допомогою "/seed gui" й перевірте, що ізумруди, портали у Краї, біоми, колодязі в пустелі та скажені гриби вимкненні, тому що вони можуть дати неправильні дані. 44 | 45 | Для знаходження сіда, з вас потребується знайти 5 структур з зазначених нижче:\ 46 | Пустельні піраміди, Храми у джунглях, Хати відьми, Розбиті кораблі, Іглу, Аванпости Розбійників 47 | 48 | Будь-яка комбінація підійде. На приклад: 3 розбитих кораблі, 1 піраміда та 1 іглу. 49 | Ви можете перевірити свій прогрес за допомогою "/seed data bits" (подивіться на кількість біт у "liftable structures") 50 | Структура була знайдена модом, якщо вона обведена. 51 | Після того як ви отримали достатньо автоматично почнеться пошук. Це займе приблизно 1-5 хв. 52 | Мод може запросити знайти ще структур після цього. 53 | Це більш імовірно, якщо у вас менше бітів та однакові структури. 54 | Після того як мод знайшов сід структур, він перебере сід мапи. 55 | 56 | ### Підтриманні структури 57 | - Підводний Монумент 58 | - Місто Краю 59 | - Захованні скарби 60 | - Пустельні Піраміди 61 | - Храми у джунглях 62 | - Хати відьми 63 | - Розбиті Кораблі 64 | - Іглу 65 | - Аванпости Розбійників 66 | 67 | ### Підтриманні декорації 68 | - Спавнери 69 | - Портали у Краї 70 | - Пустельні Колодязі 71 | - Ізумрудові руди 72 | - Скажені Гриби 73 | 74 | ## Команди 75 | 76 | Для 1.19.3 використовуйте команду 77 | - `/seedcracker` 78 | 79 | ### Команда графічного інтерфейсу 80 | - `/seed gui` 81 | 82 | Відкриває графічний інтерфейс з налаштуваннями, наприклад версія сервера, всі шукачі та база даних. 83 | Для цього всього є альтернативні команди, але не рекомендовано їми користуватися. 84 | 85 | ### Команда перезапуску пошукача 86 | - `/seed finder reload` 87 | 88 | Пересканує завантаженні чанки, щоб знайти структури, які не були знайдені. 89 | 90 | ### Команди даних 91 | - `/seed data clear` 92 | 93 | Видаляє усі зібранні дані. Корисно на мульті-мапових серверах. 94 | 95 | - `/seed data bits` 96 | 97 | Відображає скільки бітів інформації було зібрано. 98 | Звичайні біти використовуються для веж Краю та структур. Пошук починається, коли було зібрано як найменш 32 біти. 99 | Підйомні біти використовуються для підйомних структур. Пошук починається, коли було зібрано як найменш 40 біт. 100 | 101 | - `/seed data restore` 102 | 103 | Коли ви виходите з сервера, мод зберігає зібрані структури в файл у папці .minecraft/config. 104 | Після перепідключення ви можете вернути цю інформацію цією командою. 105 | 106 | 107 | ### Команди відладки 108 | - `/seed cracker debug` 109 | 110 | Показ додаткової інформації. 111 | 112 | ### Команди бази даних 113 | - `/seed database` 114 | 115 | Відкриває [Google таблицю](https://docs.google.com/spreadsheets/d/1tuQiE-0leW88em9OHbZnH-RFNhVqgoHhIt9WQbeqqWw/edit?usp=sharing), у яку мод додає сіди серверів 116 | 117 | ## Відео туторіали(англійська) 118 | 119 | Neil: 120 | - [1.15](https://youtu.be/1ChmLi9og8Q) 121 | - [1.16](https://youtu.be/aUuPSZVPH8E) 122 | 123 | 124 | Dyiing 125 | - [1.18](https://www.youtube.com/watch?v=tKeEyx7jIE4) 126 | 127 | 128 | Від мене: 129 | - [Знаходження за допомогою веж Краю та спавнерів](https://youtu.be/8ytfZ2MXosY) 130 | - [Знаходження у незері](https://youtu.be/HKjwgofhKs4) 131 | - [Знаходження за структурами](https://youtu.be/UXVrBaOR8H0) 132 | 133 | 134 | ## Підготовка до роботи 135 | 136 | -Зклонюйте репозіторій. 137 | 138 | -Виконайте `gradlew genSources `. 139 | 140 | ## Cкомпілюйте мод 141 | 142 | -Оновіть версію у `build.gradle` та `fabric.mod.json`. 143 | 144 | -Виконайте `gradlew build`. 145 | 146 | ## API для інших модів 147 | 148 | - Включіть seedcracker-api та jitpack у своєму build.gradle 149 | 150 | repositories { 151 | mavenCentral() 152 | maven { url "https://jitpack.io" } 153 | } 154 | 155 | dependencies { 156 | implementation (include('com.github.19MisterX98.SeedcrackerX:seedcrackerx-api:master-SNAPSHOT')) {transitive = false} 157 | } 158 | 159 | - Додайте клас, який реалізує інтерфейс api 160 | 161 | package misterx.myMod.seedManagemnet.SeedCrackerEP 162 | 163 | import kaptainwutax.seedcrackerX.api.SeedCrackerAPI; 164 | 165 | public class SeedCrackerEP implements SeedCrackerAPI { 166 | @Override 167 | public void pushWorldSeed(long seed) { 168 | //do something 169 | Foo.bar(seed) 170 | } 171 | } 172 | 173 | - Розкажіть fabric.mod.json де знаходиться початок виконання 174 | 175 | "entrypoints": { 176 | "main": [...], 177 | "client": [...], 178 | "server": [...], 179 | "seedcrackerx": [ 180 | "misterx.myMod.seedManagemnet.SeedCrackerEP" 181 | ] 182 | }, 183 | 184 | ## Контриб'ютори 185 | 186 | [KaptainWutax](https://github.com/KaptainWutax) - Автор 187 | 188 | [neil](https://www.youtube.com/watch?v=aUuPSZVPH8E) - Відео туторіал 189 | 190 | [Nekzuris](https://github.com/Nekzuris) - README 191 | 192 | [19MisterX98](https://www.youtube.com/channel/UCby9ZxEjJCqmccQGF3GSYlA) - Автор форку 193 | -------------------------------------------------------------------------------- /readmes/READMEzh.md: -------------------------------------------------------------------------------- 1 | # SeedCrackerX [![Github 所有版本](https://img.shields.io/github/downloads/19MisterX98/SeedCrackerX/total.svg)] 2 | 3 | 最好看英文版,中文版可能较旧 4 | 5 | ## 其他语言自述 6 | 7 | [English](../README.md) 8 | [Русский](READMEru.md) 9 | 10 | ## 我活跃在: 11 | 12 | - [我的 Discord](https://discord.gg/JRmHzqQYfp) 13 | - [Youtube](https://www.youtube.com/channel/UCby9ZxEjJCqmccQGF3GSYlA) 14 | 15 | ## 安装 16 | 下载并安装[fabric模组加载器](https://fabricmc.net/use/) 17 | 18 | 下载并安装SeedCrackerX的[发布或预发布](https://github.com/19MisterX98/SeedCrackerX/releases)版 19 | 20 | 把.jar文件放在你的mods目录下, 或者是%appdata%/.minecraft/mods/文件夹, 用于官方启动器, 或者是你自己的MultiMC实例文件夹. 21 | 22 | #### 可选 23 | 24 | 下载最新的Multiconnect[发布版](https://github.com/Earthcomputer/multiconnect/releases)用于连接到低版本的MC服务器 25 | 26 | ## 数据库 27 | 28 | 由于mod被很多人使用,我决定为服务器种子创建一个Google表格. 29 | 如果您在配置gui中启用数据库选项,该mod将直接发送被10个以上玩家破解的服务器的种子到Google表格. 30 | 31 | [表格](https://docs.google.com/spreadsheets/d/1tuQiE-0leW88em9OHbZnH-RFNhVqgoHhIt9WQbeqqWw/edit?usp=sharing) 32 | 33 | ## 使用方法 34 | ### 1.17.X及以下 35 | 36 | 在这个世界上跑来跑去,直到Mod找到一个地牢.当Mod找到一个地牢后,破解过程就会自动开始. 37 | 如果它没有获取世界种子,你可能需要找另一个地牢. 38 | 39 | 此Mod也支持通过以下方式来破解种子. 40 | - [结构和黑曜石柱](https://youtu.be/aUuPSZVPH8E?t=462) 41 | - [诡异菌](https://youtu.be/HKjwgofhKs4) 42 | 43 | ### 1.18.X及未来版本 44 | 45 | 地牢破解,诡异菌破解不再起作用。 46 | 47 | 通过“/seed gui”进入配置菜单并确保绿宝石矿石、末地折跃门、生物群系、沙漠水井和诡异菌被禁用,因为它们没有更新并且可能提供错误的数据. 48 | 49 | 为了破解你现在需要找到下列结构中至少 5 个: 50 | 沙漠神殿、丛林神殿、女巫小屋、沉船、雪屋、掠夺者前哨站。 51 | 52 | 任何组合都是有效的。例如:3 艘沉船、1 座金字塔和 1 座冰屋。 53 | 您可以使用“/seed data bits”查看您的进程。(查看可挖掘结构的位数) 54 | 当结构周围有轮廓时,就代表Mod找到了结构。 55 | 在你得到足够的数据后,破解过程会自动开始。需要 1-5 分钟。 56 | 在这之后,mod可能会要求你寻找额外的结构。 57 | 相同类型的比特和结构越少,就越有可能找到。 58 | 减少你的结构种子后,该mod将通过地牢位置或散列的种子对你的世界种子进行暴力破解. 59 | 60 | ### 支持的结构 61 | - Ocean Monument(海底神殿) 62 | - End City(末地城) 63 | - Buried Treasure(埋藏的宝藏) 64 | - Desert Pyramid(沙漠神殿) 65 | - Jungle Temple(丛林神庙) 66 | - Swamp Hut(沼泽小屋) 67 | - Shipwreck(沉船) 68 | - Igloo(雪屋) 69 | - Pillager Outpost(掠夺者前哨站) 70 | 71 | ### 支持的装饰 72 | - Dungeon(地牢) 73 | - End Gateway(末地折跃门) 74 | - Desert Well(沙漠水井) 75 | - Emerald Ore(绿宝石矿石) 76 | - Warped Fungus(诡异菌) 77 | 78 | ## 命令. 79 | 80 | ### GUI命令 81 | - `/seed gui` 82 | 打开配置gui,您可以在其中修改服务器MC版本等设置,所有搜索器、数据库和渲染模式. 83 | 大多数命令都有替代品,所以它们不应该再被使用了 84 | 85 | ### 搜索器重新搜索命令 86 | - `/seed finder reload` 87 | 88 | 重新扫描加载的区块以查找以前未找到的结构. 89 | 90 | ### 数据指令 91 | - `/seed data clear` 92 | 93 | 无需重新登录即可清除所有收集的数据. 这对多世界的服务器很有用. 94 | 95 | - `/seed data bits` 96 | 97 | 显示已经收集了多少比特的信息. 尽管这是一个近似值, 但它可以作为一个很好的参考来猜测什么时候应该开始进行暴力破解。 98 | 普通比特用于黑曜石柱和结构破解. 破解从 32 位开始. 99 | 挖掘比特用于可挖掘结构破解. 破解从 40 位开始. 100 | 101 | - `/seed data restore` 102 | 103 | 当你离开一个世界时, mod会将当前收集的结构信息保存在一个文件中,在 .minecraft/config 目录. 104 | 重新进入后, 你可以用此命令恢复它. 105 | 106 | ### 调试命令 107 | - `/seed cracker debug` 108 | 109 | 显示调试信息 110 | 111 | ### 数据库命令 112 | - `/seed database` 113 | 114 | 打开一个[google表格](https://docs.google.com/spreadsheets/d/1tuQiE-0leW88em9OHbZnH-RFNhVqgoHhIt9WQbeqqWw/edit?usp=sharing)由mod维护 115 | 116 | ## 视频教程 117 | 118 | Neil的: 119 | - [1.15](https://youtu.be/1ChmLi9og8Q) 120 | - [1.16](https://youtu.be/aUuPSZVPH8E) 121 | 122 | 123 | 我的: 124 | - [地牢破解和黑曜石柱破解](https://youtu.be/8ytfZ2MXosY) 125 | - [下界破解](https://youtu.be/HKjwgofhKs4) 126 | - [结构破解](https://youtu.be/UXVrBaOR8H0) 127 | ## 设置工作区 128 | 129 | -克隆此仓库. 130 | 131 | -运行 `gradlew genSources `. 132 | 133 | ## 编译此Mod 134 | 135 | -在 `build.gradle` 和 `fabric.mod.json` 里更新版本. 136 | 137 | -运行 `gradlew build`. 138 | 139 | ## 对于其他mod的API接口 140 | 141 | - 在你的build.gradle中包含seedcracker-api和jitpack 142 | 143 | repositories { 144 | mavenCentral() 145 | maven { url "https://jitpack.io" } 146 | } 147 | 148 | dependencies { 149 | implementation (include('com.github.19MisterX98.SeedcrackerX:seedcrackerx-api:master-SNAPSHOT')) {transitive = false} 150 | } 151 | 152 | - 添加一个实现api接口的类 153 | 154 | package misterx.myMod.seedManagemnet.SeedCrackerEP 155 | 156 | import kaptainwutax.seedcrackerX.api.SeedCrackerAPI; 157 | 158 | public class SeedCrackerEP implements SeedCrackerAPI { 159 | @Override 160 | public void pushWorldSeed(long seed) { 161 | //do something 162 | Foo.bar(seed) 163 | } 164 | } 165 | 166 | - 告诉fabric.mod.json你的入口点在哪里 167 | 168 | "entrypoints": { 169 | "main": [...], 170 | "client": [...], 171 | "server": [...], 172 | "seedcrackerx": [ 173 | "misterx.myMod.seedManagemnet.SeedCrackerEP" 174 | ] 175 | }, 176 | 177 | ## 贡献者 178 | 179 | [KaptainWutax](https://github.com/KaptainWutax) - 原作者 180 | 181 | [neil](https://www.youtube.com/watch?v=aUuPSZVPH8E) - 视频教程 182 | 183 | [Nekzuris](https://github.com/Nekzuris) - README 184 | 185 | [19MisterX98](https://www.youtube.com/channel/UCby9ZxEjJCqmccQGF3GSYlA) - 作者 186 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { 4 | name = 'Fabric' 5 | url = 'https://maven.fabricmc.net/' 6 | } 7 | gradlePluginPortal() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/Features.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX; 2 | 3 | import com.seedfinding.mccore.version.MCVersion; 4 | import com.seedfinding.mcfeature.Feature; 5 | import com.seedfinding.mcfeature.decorator.DesertWell; 6 | import com.seedfinding.mcfeature.decorator.EndGateway; 7 | import com.seedfinding.mcfeature.structure.*; 8 | import kaptainwutax.seedcrackerX.cracker.decorator.DeepDungeon; 9 | import kaptainwutax.seedcrackerX.cracker.decorator.Dungeon; 10 | import kaptainwutax.seedcrackerX.cracker.decorator.EmeraldOre; 11 | import kaptainwutax.seedcrackerX.cracker.decorator.WarpedFungus; 12 | import kaptainwutax.seedcrackerX.finder.Finder; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.function.Supplier; 17 | 18 | public class Features { 19 | public static final ArrayList> STRUCTURE_TYPES = new ArrayList<>(); 20 | 21 | public static BuriedTreasure BURIED_TREASURE; 22 | public static DesertPyramid DESERT_PYRAMID; 23 | public static EndCity END_CITY; 24 | public static JunglePyramid JUNGLE_PYRAMID; 25 | public static Monument MONUMENT; 26 | public static Shipwreck SHIPWRECK; 27 | public static SwampHut SWAMP_HUT; 28 | public static PillagerOutpost PILLAGER_OUTPOST; 29 | public static Igloo IGLOO; 30 | 31 | public static EndGateway END_GATEWAY; 32 | public static DesertWell DESERT_WELL; 33 | public static EmeraldOre EMERALD_ORE; 34 | public static Dungeon DUNGEON; 35 | public static DeepDungeon DEEP_DUNGEON; 36 | public static WarpedFungus WARPED_FUNGUS; 37 | 38 | public static void init(MCVersion version) { 39 | STRUCTURE_TYPES.clear(); 40 | 41 | BURIED_TREASURE = safe(STRUCTURE_TYPES, Finder.Type.BURIED_TREASURE, () -> new BuriedTreasure(version)); 42 | DESERT_PYRAMID = safe(STRUCTURE_TYPES, Finder.Type.DESERT_TEMPLE, () -> new DesertPyramid(version)); 43 | END_CITY = safe(STRUCTURE_TYPES, Finder.Type.END_CITY, () -> new EndCity(version)); 44 | JUNGLE_PYRAMID = safe(STRUCTURE_TYPES, Finder.Type.JUNGLE_TEMPLE, () -> new JunglePyramid(version)); 45 | MONUMENT = safe(STRUCTURE_TYPES, Finder.Type.MONUMENT, () -> new Monument(version)); 46 | SHIPWRECK = safe(STRUCTURE_TYPES, Finder.Type.SHIPWRECK, () -> new Shipwreck(version)); 47 | SWAMP_HUT = safe(STRUCTURE_TYPES, Finder.Type.SWAMP_HUT, () -> new SwampHut(version)); 48 | PILLAGER_OUTPOST = safe(STRUCTURE_TYPES, Finder.Type.PILLAGER_OUTPOST, () -> new PillagerOutpost(version)); 49 | IGLOO = safe(STRUCTURE_TYPES, Finder.Type.IGLOO, () -> new Igloo(version)); 50 | 51 | END_GATEWAY = safe(Finder.Type.END_GATEWAY, () -> new EndGateway(version)); 52 | DESERT_WELL = safe(Finder.Type.DESERT_WELL, () -> new DesertWell(version)); 53 | EMERALD_ORE = safe(Finder.Type.EMERALD_ORE, () -> new EmeraldOre(version)); 54 | DUNGEON = safe(Finder.Type.DUNGEON, () -> new Dungeon(version)); 55 | DEEP_DUNGEON = safe(Finder.Type.DUNGEON, () -> new DeepDungeon(version)); 56 | WARPED_FUNGUS = safe(Finder.Type.WARPED_FUNGUS, () -> new WarpedFungus(version)); 57 | 58 | STRUCTURE_TYPES.trimToSize(); 59 | } 60 | 61 | private static > F safe(Finder.Type finderType, Supplier lambda) { 62 | try { 63 | return lambda.get(); 64 | } catch (Throwable t) { 65 | SeedCracker.LOGGER.error("Exception thrown loading feature", t); 66 | finderType.enabled.set(false); 67 | return null; 68 | } 69 | } 70 | 71 | private static > F safe(List> list, Finder.Type finderType, Supplier lambda) { 72 | F initializedFeature = safe(finderType, lambda); 73 | if (initializedFeature != null) list.add(initializedFeature); 74 | return initializedFeature; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/SeedCracker.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX; 2 | 3 | import com.mojang.logging.LogUtils; 4 | import kaptainwutax.seedcrackerX.api.SeedCrackerAPI; 5 | import kaptainwutax.seedcrackerX.config.Config; 6 | import kaptainwutax.seedcrackerX.cracker.storage.DataStorage; 7 | import kaptainwutax.seedcrackerX.finder.FinderQueue; 8 | import kaptainwutax.seedcrackerX.init.ClientCommands; 9 | import kaptainwutax.seedcrackerX.util.Database; 10 | import net.fabricmc.api.ModInitializer; 11 | import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; 12 | import net.fabricmc.loader.api.FabricLoader; 13 | import org.slf4j.Logger; 14 | 15 | import java.util.ArrayList; 16 | 17 | public class SeedCracker implements ModInitializer { 18 | public static final Logger LOGGER = LogUtils.getLogger(); 19 | public static final ArrayList entrypoints = new ArrayList<>(); 20 | private static SeedCracker INSTANCE; 21 | private final DataStorage dataStorage = new DataStorage(); 22 | 23 | public static SeedCracker get() { 24 | return INSTANCE; 25 | } 26 | 27 | @Override 28 | public void onInitialize() { 29 | INSTANCE = this; 30 | Config.load(); 31 | Features.init(Config.get().getVersion()); 32 | FabricLoader.getInstance().getEntrypointContainers("seedcrackerx", SeedCrackerAPI.class).forEach(entrypoint -> 33 | entrypoints.add(entrypoint.getEntrypoint())); 34 | 35 | ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> ClientCommands.registerCommands(dispatcher)); 36 | 37 | Database.fetchSeeds(); 38 | } 39 | 40 | public DataStorage getDataStorage() { 41 | return this.dataStorage; 42 | } 43 | 44 | public void reset() { 45 | SeedCracker.get().getDataStorage().clear(); 46 | FinderQueue.get().finderControl.deleteFinders(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/api/SeedCrackerAPI.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.api; 2 | 3 | public interface SeedCrackerAPI { 4 | 5 | void pushWorldSeed(long seed); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/command/ClientCommand.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.command; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 5 | import kaptainwutax.seedcrackerX.init.ClientCommands; 6 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; 7 | import kaptainwutax.seedcrackerX.util.Log; 8 | import net.minecraft.client.MinecraftClient; 9 | import net.minecraft.text.Text; 10 | import net.minecraft.util.Formatting; 11 | 12 | import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; 13 | 14 | 15 | public abstract class ClientCommand { 16 | 17 | public static void sendFeedback(String message, Formatting color, boolean overlay) { 18 | try { 19 | MinecraftClient.getInstance().player.sendMessage(Text.literal(message).formatted(color), overlay); 20 | } catch (Exception e) { 21 | } 22 | } 23 | 24 | public abstract String getName(); 25 | 26 | public abstract void build(LiteralArgumentBuilder builder); 27 | 28 | public final void register(CommandDispatcher dispatcher) { 29 | LiteralArgumentBuilder builder = literal(this.getName()); 30 | this.build(builder); 31 | LiteralArgumentBuilder seedCrackerRootCommand = literal(ClientCommands.PREFIX) 32 | .executes(context -> { 33 | Log.error("Error: please enter a valid seedcracker command"); 34 | return 1; 35 | }); 36 | dispatcher.register(seedCrackerRootCommand.then(builder)); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/command/CrackerCommand.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.command; 2 | 3 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 4 | import kaptainwutax.seedcrackerX.config.Config; 5 | import kaptainwutax.seedcrackerX.util.Log; 6 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; 7 | import net.minecraft.util.Formatting; 8 | 9 | import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; 10 | 11 | public class CrackerCommand extends ClientCommand { 12 | 13 | @Override 14 | public String getName() { 15 | return "cracker"; 16 | } 17 | 18 | @Override 19 | public void build(LiteralArgumentBuilder builder) { 20 | builder.then(literal("ON").executes(context -> this.setActive(true))) 21 | .then(literal("OFF").executes(context -> this.setActive(false))) 22 | .executes(context -> this.toggleActive()); 23 | 24 | builder.then(literal("debug") 25 | .then(literal("ON").executes(context -> this.setDebug(true))) 26 | .then(literal("OFF").executes(context -> this.setDebug(false))) 27 | .executes(context -> this.toggleDebug())); 28 | } 29 | 30 | private void feedback(boolean success, boolean flag) { 31 | String action = Log.translate(flag ? "cracker.enabled" : "cracker.disabled"); 32 | if (success) { 33 | sendFeedback(Log.translate("cracker.successfully") + action, Formatting.GREEN, false); 34 | } else { 35 | sendFeedback(Log.translate("cracker.already") + action, Formatting.RED, false); 36 | } 37 | Config.save(); 38 | } 39 | 40 | private int setActive(boolean flag) { 41 | feedback(Config.get().active != flag, flag); 42 | Config.get().active = flag; 43 | return 0; 44 | } 45 | 46 | private int toggleActive() { 47 | Config.get().active = !Config.get().active; 48 | feedback(true, Config.get().active); 49 | return 0; 50 | } 51 | 52 | private int setDebug(boolean flag) { 53 | feedback(Config.get().debug != flag, flag); 54 | Config.get().debug = flag; 55 | return 0; 56 | } 57 | 58 | private int toggleDebug() { 59 | Config.get().debug = !Config.get().debug; 60 | feedback(true, Config.get().debug); 61 | return 0; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/command/DataCommand.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.command; 2 | 3 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 4 | import com.mojang.brigadier.context.CommandContext; 5 | import com.seedfinding.mcfeature.structure.RegionStructure; 6 | import kaptainwutax.seedcrackerX.SeedCracker; 7 | import kaptainwutax.seedcrackerX.config.StructureSave; 8 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 9 | import kaptainwutax.seedcrackerX.cracker.storage.DataStorage; 10 | import kaptainwutax.seedcrackerX.util.Log; 11 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; 12 | import net.minecraft.util.Formatting; 13 | import net.minecraft.util.Language; 14 | 15 | import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; 16 | 17 | public class DataCommand extends ClientCommand { 18 | 19 | @Override 20 | public String getName() { 21 | return "data"; 22 | } 23 | 24 | @Override 25 | public void build(LiteralArgumentBuilder builder) { 26 | builder.then(literal("clear") 27 | .executes(this::clear) 28 | ); 29 | 30 | builder.then(literal("bits") 31 | .executes(this::printBits) 32 | ); 33 | 34 | builder.then(literal("restore") 35 | .executes(this::restoreData) 36 | ); 37 | } 38 | 39 | public int clear(CommandContext context) { 40 | SeedCracker.get().reset(); 41 | 42 | sendFeedback(Language.getInstance().get("data.clearData"), Formatting.GREEN, false); 43 | return 0; 44 | } 45 | 46 | private int printBits(CommandContext context) { 47 | DataStorage s = SeedCracker.get().getDataStorage(); 48 | String message = Language.getInstance().get("data.collectedBits").formatted((int) s.getBaseBits(), (int) s.getWantedBits()); 49 | String message2 = Language.getInstance().get("data.collectedLiftingBits").formatted((int) s.getLiftingBits(), 40); 50 | sendFeedback(message, Formatting.GREEN, false); 51 | sendFeedback(message2, Formatting.GREEN, false); 52 | return 0; 53 | } 54 | 55 | private int restoreData(CommandContext context) { 56 | var preloaded = StructureSave.loadStructures(); 57 | if (!preloaded.isEmpty()) { 58 | for (RegionStructure.Data data : preloaded) { 59 | SeedCracker.get().getDataStorage().addBaseData(data, DataAddedEvent.POKE_LIFTING); 60 | } 61 | Log.warn("data.restoreStructures",preloaded.size()); 62 | } else { 63 | Log.warn("data.restoreFailed"); 64 | } 65 | return 0; 66 | } 67 | 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/command/DatabaseCommand.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.command; 2 | 3 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 4 | import com.mojang.brigadier.context.CommandContext; 5 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; 6 | import net.minecraft.util.Util; 7 | 8 | import java.net.URI; 9 | 10 | public class DatabaseCommand extends ClientCommand { 11 | 12 | public static URI DATABASE_URL = URI.create("https://docs.google.com/spreadsheets/d/1tuQiE-0leW88em9OHbZnH-RFNhVqgoHhIt9WQbeqqWw/edit?usp=sharing"); 13 | 14 | @Override 15 | public String getName() { 16 | return "database"; 17 | } 18 | 19 | @Override 20 | public void build(LiteralArgumentBuilder builder) { 21 | builder.executes(this::openURL); 22 | } 23 | 24 | public int openURL(CommandContext context) { 25 | Util.getOperatingSystem().open(DATABASE_URL); 26 | return 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/command/FinderCommand.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.command; 2 | 3 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 4 | import kaptainwutax.seedcrackerX.config.Config; 5 | import kaptainwutax.seedcrackerX.finder.Finder; 6 | import kaptainwutax.seedcrackerX.finder.ReloadFinders; 7 | import kaptainwutax.seedcrackerX.util.Log; 8 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; 9 | import net.minecraft.util.Formatting; 10 | 11 | import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; 12 | 13 | public class FinderCommand extends ClientCommand { 14 | ReloadFinders reloadFinders = new ReloadFinders(); 15 | 16 | @Override 17 | public String getName() { 18 | return "finder"; 19 | } 20 | 21 | @Override 22 | public void build(LiteralArgumentBuilder builder) { 23 | for (Finder.Type finderType : Finder.Type.values()) { 24 | builder.then(literal("type") 25 | .then(literal(finderType.toString()) 26 | .then(literal("ON").executes(context -> this.setFinderType(finderType, true, true))) 27 | .then(literal("OFF").executes(context -> this.setFinderType(finderType, false, true))) 28 | .executes(context -> this.printFinderType(finderType))) 29 | ); 30 | } 31 | 32 | for (Finder.Category finderCategory : Finder.Category.values()) { 33 | builder.then(literal("category") 34 | .then(literal(finderCategory.toString()) 35 | .then(literal("ON").executes(context -> this.setFinderCategory(finderCategory, true))) 36 | .then(literal("OFF").executes(context -> this.setFinderCategory(finderCategory, false))) 37 | .executes(context -> this.printFinderCategory(finderCategory))) 38 | ); 39 | } 40 | builder.then(literal("reload").executes(context -> this.reload())); 41 | } 42 | 43 | private int printFinderCategory(Finder.Category finderCategory) { 44 | Finder.Type.getForCategory(finderCategory).forEach(this::printFinderType); 45 | return 0; 46 | } 47 | 48 | private int printFinderType(Finder.Type finderType) { 49 | sendFeedback(Log.translate("finder.isFinder").formatted(Log.translate(finderType.nameKey)) + " [" + String.valueOf(finderType.enabled.get()).toUpperCase() + "].", Formatting.AQUA, false); 50 | return 0; 51 | } 52 | 53 | private int setFinderCategory(Finder.Category finderCategory, boolean flag) { 54 | Finder.Type.getForCategory(finderCategory).forEach(finderType -> this.setFinderType(finderType, flag, false)); 55 | Config.save(); 56 | return 0; 57 | } 58 | 59 | private int setFinderType(Finder.Type finderType, boolean flag, boolean save) { 60 | finderType.enabled.set(flag); 61 | if (save) Config.save(); 62 | sendFeedback(Log.translate("finder.setFinder").formatted(Log.translate(finderType.nameKey)) + " [" + String.valueOf(flag).toUpperCase() + "].", Formatting.AQUA, false); 63 | return 0; 64 | } 65 | 66 | private int reload() { 67 | reloadFinders.reload(); 68 | return 0; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/command/GuiCommand.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.command; 2 | 3 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 4 | import com.mojang.brigadier.context.CommandContext; 5 | import kaptainwutax.seedcrackerX.SeedCracker; 6 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; 7 | 8 | public class GuiCommand extends ClientCommand { 9 | 10 | @Override 11 | public String getName() { 12 | return "gui"; 13 | } 14 | 15 | @Override 16 | public void build(LiteralArgumentBuilder builder) { 17 | builder.executes(this::openGui); 18 | } 19 | 20 | private int openGui(CommandContext context) { 21 | SeedCracker.get().getDataStorage().openGui = true; //gui needs to open on the main thread 22 | return 0; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/command/RenderCommand.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.command; 2 | 3 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 4 | import kaptainwutax.seedcrackerX.config.Config; 5 | import kaptainwutax.seedcrackerX.util.Log; 6 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; 7 | import net.minecraft.util.Formatting; 8 | 9 | import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; 10 | 11 | public class RenderCommand extends ClientCommand { 12 | 13 | @Override 14 | public String getName() { 15 | return "render"; 16 | } 17 | 18 | @Override 19 | public void build(LiteralArgumentBuilder builder) { 20 | builder.then(literal("outlines") 21 | .executes(context -> this.printRenderMode()) 22 | ); 23 | 24 | for (Config.RenderType renderType : Config.RenderType.values()) { 25 | builder.then(literal("outlines") 26 | .then(literal(renderType.toString()).executes(context -> this.setRenderMode(renderType))) 27 | ); 28 | } 29 | } 30 | 31 | private int printRenderMode() { 32 | sendFeedback(Log.translate("render.getRenderMode") + " [" + Config.get().render + "].", Formatting.AQUA, false); 33 | return 0; 34 | } 35 | 36 | private int setRenderMode(Config.RenderType renderType) { 37 | Config.get().render = renderType; 38 | Config.save(); 39 | sendFeedback(Log.translate("render.setRenderMode") + " [" + Config.get().render + "].", Formatting.AQUA, false); 40 | return 0; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/command/VersionCommand.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.command; 2 | 3 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 4 | import com.seedfinding.mccore.version.MCVersion; 5 | import kaptainwutax.seedcrackerX.config.Config; 6 | import kaptainwutax.seedcrackerX.util.Log; 7 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; 8 | import net.minecraft.util.Formatting; 9 | 10 | import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; 11 | 12 | public class VersionCommand extends ClientCommand { 13 | 14 | @Override 15 | public String getName() { 16 | return "version"; 17 | } 18 | 19 | @Override 20 | public void build(LiteralArgumentBuilder builder) { 21 | for (MCVersion version : MCVersion.values()) { 22 | if (version.isOlderThan(MCVersion.v1_8)) continue; 23 | builder.then(literal(version.name).executes(context -> this.setVersion(version))); 24 | } 25 | } 26 | 27 | private int setVersion(MCVersion version) { 28 | Config.get().setVersion(version); 29 | Config.save(); 30 | ClientCommand.sendFeedback(Log.translate("version.setVersion") + " " + version + ".", Formatting.AQUA, true); 31 | return 0; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/config/Config.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.config; 2 | 3 | 4 | import com.google.gson.Gson; 5 | import com.google.gson.GsonBuilder; 6 | import com.seedfinding.mccore.version.MCVersion; 7 | import kaptainwutax.seedcrackerX.Features; 8 | import kaptainwutax.seedcrackerX.util.FeatureToggle; 9 | 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import java.io.*; 14 | 15 | public class Config { 16 | private static final Logger logger = LoggerFactory.getLogger("config"); 17 | 18 | private static final File file = new File(net.fabricmc.loader.api.FabricLoader.getInstance().getConfigDir().toFile(), "seedcracker.json"); 19 | private static Config INSTANCE = new Config(); 20 | public FeatureToggle buriedTreasure = new FeatureToggle(true); 21 | public FeatureToggle desertTemple = new FeatureToggle(true); 22 | public FeatureToggle endCity = new FeatureToggle(true); 23 | public FeatureToggle jungleTemple = new FeatureToggle(true); 24 | public FeatureToggle monument = new FeatureToggle(true); 25 | public FeatureToggle swampHut = new FeatureToggle(true); 26 | public FeatureToggle shipwreck = new FeatureToggle(true); 27 | public FeatureToggle outpost = new FeatureToggle(true); 28 | public FeatureToggle igloo = new FeatureToggle(true); 29 | public FeatureToggle endPillars = new FeatureToggle(true); 30 | public FeatureToggle endGateway = new FeatureToggle(false); 31 | public FeatureToggle dungeon = new FeatureToggle(true); 32 | public FeatureToggle emeraldOre = new FeatureToggle(false); 33 | public FeatureToggle desertWell = new FeatureToggle(false); 34 | public FeatureToggle warpedFungus = new FeatureToggle(false); 35 | public FeatureToggle biome = new FeatureToggle(false); 36 | public RenderType render = RenderType.XRAY; 37 | public boolean active = true; 38 | public boolean debug = false; 39 | public boolean antiXrayBypass = true; 40 | private MCVersion version = MCVersion.latest(); 41 | public boolean databaseSubmits = false; 42 | public boolean anonymusSubmits = false; 43 | 44 | public static void save() { 45 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 46 | // make sure that the config directory exists 47 | file.getParentFile().mkdirs(); 48 | 49 | try (FileWriter writer = new FileWriter(file)) { 50 | gson.toJson(INSTANCE, writer); 51 | } catch (IOException e) { 52 | logger.error("seedcracker couldn't save config", e); 53 | } 54 | } 55 | 56 | public static void load() { 57 | Gson gson = new Gson(); 58 | 59 | if (!file.exists()) return; 60 | 61 | try (Reader reader = new FileReader(file)) { 62 | INSTANCE = gson.fromJson(reader, Config.class); 63 | } catch (Exception e) { 64 | logger.error("seedcracker couldn't load config, deleting it...", e); 65 | file.delete(); 66 | } 67 | } 68 | 69 | public static Config get() { 70 | return INSTANCE; 71 | } 72 | 73 | public MCVersion getVersion() { 74 | return version; 75 | } 76 | 77 | public void setVersion(MCVersion version) { 78 | if (this.version == version) return; 79 | this.version = version; 80 | Features.init(version); 81 | } 82 | 83 | public enum RenderType { 84 | OFF, ON, XRAY 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/config/ScModMenuEntry.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.config; 2 | 3 | 4 | import com.terraformersmc.modmenu.api.ConfigScreenFactory; 5 | import com.terraformersmc.modmenu.api.ModMenuApi; 6 | import net.fabricmc.api.EnvType; 7 | import net.fabricmc.api.Environment; 8 | 9 | 10 | @Environment(EnvType.CLIENT) 11 | public class ScModMenuEntry implements ModMenuApi { 12 | ConfigScreen configscreen = new ConfigScreen(); 13 | 14 | @Override 15 | public ConfigScreenFactory getModConfigScreenFactory() { 16 | return configscreen::getConfigScreenByCloth; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/config/StructureSave.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.config; 2 | 3 | import com.seedfinding.mcfeature.Feature; 4 | import com.seedfinding.mcfeature.structure.RegionStructure; 5 | import com.seedfinding.mcfeature.structure.Structure; 6 | import kaptainwutax.seedcrackerX.Features; 7 | import kaptainwutax.seedcrackerX.cracker.storage.DataStorage; 8 | import kaptainwutax.seedcrackerX.cracker.storage.ScheduledSet; 9 | import net.fabricmc.loader.api.FabricLoader; 10 | import net.minecraft.client.MinecraftClient; 11 | import net.minecraft.network.ClientConnection; 12 | import net.minecraft.util.WorldSavePath; 13 | 14 | import java.io.*; 15 | import java.nio.file.Files; 16 | import java.nio.file.Path; 17 | import java.nio.file.Paths; 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | import java.util.Scanner; 21 | 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | public class StructureSave { 26 | private static final Logger logger = LoggerFactory.getLogger("structureSave"); 27 | 28 | public static final Path saveDir = Paths.get(FabricLoader.getInstance().getConfigDir().toFile().toString(), "SeedCrackerX saved structures"); 29 | 30 | public static void saveStructures(ScheduledSet>> baseData) { 31 | try { 32 | Files.createDirectories(saveDir); 33 | Path saveFile = saveDir.resolve(getWorldName()); 34 | Files.deleteIfExists(saveFile); 35 | Files.createFile(saveFile); 36 | try (FileWriter writer = new FileWriter(saveFile.toFile())) { 37 | for (DataStorage.Entry> dataEntry : baseData) { 38 | if (dataEntry.data.feature instanceof Structure structure) { 39 | String data = Structure.getName(structure.getClass()) + 40 | ";" + dataEntry.data.chunkX + 41 | ";" + dataEntry.data.chunkZ + 42 | "\n"; 43 | writer.write(data); 44 | } 45 | } 46 | } 47 | } catch (IOException e) { 48 | logger.error("seedcracker couldn't save structures", e); 49 | } 50 | } 51 | 52 | public static List> loadStructures() { 53 | List> result = new ArrayList<>(); 54 | try { 55 | Files.createDirectories(saveDir); 56 | Path saveFile = saveDir.resolve(getWorldName()); 57 | try ( 58 | FileInputStream fis = new FileInputStream(saveFile.toFile()); 59 | Scanner sc = new Scanner(fis) 60 | ) { 61 | while (sc.hasNextLine()) { 62 | String line = sc.nextLine(); 63 | String[] info = line.split(";"); 64 | if (info.length != 3) continue; 65 | String structureName = info[0]; 66 | for (RegionStructure idk : Features.STRUCTURE_TYPES) { 67 | if (structureName.equals(idk.getName())) { 68 | result.add(idk.at(Integer.parseInt(info[1]), Integer.parseInt(info[2]))); 69 | break; 70 | } 71 | } 72 | } 73 | } 74 | } catch (FileNotFoundException e) { 75 | logger.warn("seedcracker couldn't find a structures file"); 76 | return result; 77 | } catch (IOException e) { 78 | logger.error("seedcracker couldn't load previous structures", e); 79 | } 80 | return result; 81 | } 82 | 83 | private static String getWorldName() { 84 | MinecraftClient minecraftClient = MinecraftClient.getInstance(); 85 | if (minecraftClient.getNetworkHandler() != null) { 86 | ClientConnection connection = minecraftClient.getNetworkHandler().getConnection(); 87 | if (connection.isLocal()) { 88 | String address = minecraftClient.getServer().getSavePath(WorldSavePath.ROOT).getParent().getFileName().toString(); 89 | return address.replace("/","_").replace(":", "_")+".txt"; 90 | } else { 91 | return connection.getAddress().toString().replace("/","_").replace(":","_")+".txt"; 92 | } 93 | } 94 | return "Invalid.txt"; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/cracker/BiomeData.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.cracker; 2 | 3 | import com.seedfinding.mcbiome.biome.Biome; 4 | import com.seedfinding.mcbiome.source.BiomeSource; 5 | import com.seedfinding.mccore.version.MCVersion; 6 | import kaptainwutax.seedcrackerX.config.Config; 7 | 8 | public class BiomeData { 9 | 10 | public final Biome biome; 11 | public final int x; 12 | public final int z; 13 | 14 | public BiomeData(Biome biome, int x, int z) { 15 | this.biome = biome; 16 | this.x = x; 17 | this.z = z; 18 | } 19 | 20 | public boolean test(BiomeSource source) { 21 | if (Config.get().getVersion().isNewerOrEqualTo(MCVersion.v1_15)) { 22 | return source.getBiomeForNoiseGen(this.x, 0, this.z) == this.biome; 23 | } else { 24 | return source.getBiome(this.x, 0, this.z) == this.biome; 25 | } 26 | } 27 | 28 | @Override 29 | public boolean equals(Object o) { 30 | if (this == o) return true; 31 | if (!(o instanceof BiomeData)) return false; 32 | BiomeData data = (BiomeData) o; 33 | return this.biome == data.biome; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | return this.biome.getName().hashCode(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/cracker/DataAddedEvent.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.cracker; 2 | 3 | import kaptainwutax.seedcrackerX.cracker.storage.DataStorage; 4 | import kaptainwutax.seedcrackerX.cracker.storage.TimeMachine; 5 | 6 | @FunctionalInterface 7 | public interface DataAddedEvent { 8 | 9 | DataAddedEvent POKE_PILLARS = s -> s.getTimeMachine().poke(TimeMachine.Phase.PILLARS); 10 | DataAddedEvent POKE_STRUCTURES = s -> s.getTimeMachine().poke(TimeMachine.Phase.STRUCTURES); 11 | DataAddedEvent POKE_LIFTING = s -> s.getTimeMachine().poke(TimeMachine.Phase.LIFTING); 12 | DataAddedEvent POKE_BIOMES = s -> s.getTimeMachine().poke(TimeMachine.Phase.BIOMES); 13 | 14 | void onDataAdded(DataStorage dataStorage); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/cracker/HashedSeedData.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.cracker; 2 | 3 | import com.seedfinding.mccore.rand.seed.WorldSeed; 4 | import com.seedfinding.mcseed.rand.JRand; 5 | 6 | public class HashedSeedData { 7 | 8 | private final long hashedSeed; 9 | 10 | public HashedSeedData(long hashedSeed) { 11 | this.hashedSeed = hashedSeed; 12 | } 13 | 14 | public boolean test(long seed, JRand rand) { 15 | return WorldSeed.toHash(seed) == this.hashedSeed; 16 | } 17 | 18 | public long getHashedSeed() { 19 | return this.hashedSeed; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/cracker/PillarData.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.cracker; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.Random; 7 | 8 | public class PillarData { 9 | 10 | private final List heights; 11 | 12 | public PillarData(List heights) { 13 | this.heights = heights; 14 | } 15 | 16 | public boolean test(long seed) { 17 | List h = this.getPillarHeights((int) seed); 18 | return h.equals(this.heights); 19 | } 20 | 21 | public List getPillarHeights(int pillarSeed) { 22 | List indices = new ArrayList<>(); 23 | 24 | for (int i = 0; i < 10; i++) { 25 | indices.add(i); 26 | } 27 | 28 | Collections.shuffle(indices, new Random(pillarSeed)); 29 | 30 | List heights = new ArrayList<>(); 31 | 32 | for (Integer index : indices) { 33 | heights.add(76 + index * 3); 34 | } 35 | 36 | return heights; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/cracker/decorator/Decorator.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.cracker.decorator; 2 | 3 | import com.seedfinding.mcbiome.biome.Biome; 4 | import com.seedfinding.mcbiome.source.BiomeSource; 5 | import com.seedfinding.mccore.rand.ChunkRand; 6 | import com.seedfinding.mccore.version.MCVersion; 7 | import com.seedfinding.mcfeature.Feature; 8 | import com.seedfinding.mcterrain.TerrainGenerator; 9 | import net.minecraft.util.math.random.ChunkRandom; 10 | 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | public abstract class Decorator> extends Feature { 15 | 16 | public Decorator(C config, MCVersion version) { 17 | super(config, version); 18 | } 19 | 20 | public int getIndex(Biome biome) { 21 | return this.getConfig().getSalt(biome) % 10000; 22 | } 23 | 24 | public int getStep(Biome biome) { 25 | return this.getConfig().getSalt(biome) / 10000; 26 | } 27 | 28 | @Override 29 | public boolean canStart(D data, long structureSeed, ChunkRand rand) { 30 | rand.setDecoratorSeed(structureSeed, data.chunkX << 4, data.chunkZ << 4, 31 | this.getIndex(data.biome), this.getStep(data.biome), this.getVersion()); 32 | return true; 33 | } 34 | 35 | public boolean canStart(D data, long worldSeed, ChunkRandom rand) { 36 | long l = rand.setPopulationSeed(worldSeed, data.chunkX << 4, data.chunkZ << 4); 37 | rand.setDecoratorSeed(l, this.getIndex(data.biome), this.getStep(data.biome)); 38 | return true; 39 | } 40 | 41 | @Override 42 | public boolean canGenerate(D data, TerrainGenerator generator) { 43 | return true; 44 | } 45 | 46 | @Override 47 | public final boolean canSpawn(D data, BiomeSource source) { 48 | return this.canSpawn(data.chunkX, data.chunkZ, source); 49 | } 50 | 51 | public boolean canSpawn(int chunkX, int chunkZ, BiomeSource source) { 52 | if (this.getVersion().isOlderThan(MCVersion.v1_16)) { 53 | return this.isValidBiome(source.getBiome((chunkX << 4) + 8, 0, (chunkZ << 4) + 8)); 54 | } 55 | 56 | return this.isValidBiome(source.getBiomeForNoiseGen((chunkX << 2) + 2, 0, (chunkZ << 2) + 2)); 57 | } 58 | 59 | public abstract boolean isValidBiome(Biome biome); 60 | 61 | public static class Config extends Feature.Config { 62 | public final int defaultSalt; 63 | public final Map salts = new HashMap<>(); 64 | 65 | public Config(int step, int index) { 66 | this.defaultSalt = step * 10000 + index; 67 | } 68 | 69 | public Config add(int step, int index, Biome... biomes) { 70 | for (Biome biome : biomes) { 71 | this.salts.put(biome, step * 10000 + index); 72 | } 73 | 74 | return this; 75 | } 76 | 77 | public int getSalt(Biome biome) { 78 | return this.salts.getOrDefault(biome, this.defaultSalt); 79 | } 80 | } 81 | 82 | public static class Data> extends Feature.Data { 83 | public final Biome biome; 84 | 85 | public Data(T feature, int chunkX, int chunkZ, Biome biome) { 86 | super(feature, chunkX, chunkZ); 87 | this.biome = biome; 88 | } 89 | 90 | public boolean testStart(long worldSeed, ChunkRandom rand) { 91 | return ((Decorator) this.feature).canStart(this, worldSeed, rand); 92 | } 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/cracker/decorator/DeepDungeon.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.cracker.decorator; 2 | 3 | import com.seedfinding.mcbiome.biome.Biome; 4 | import com.seedfinding.mcbiome.biome.Biomes; 5 | import com.seedfinding.mccore.rand.ChunkRand; 6 | import com.seedfinding.mccore.state.Dimension; 7 | import com.seedfinding.mccore.version.MCVersion; 8 | import com.seedfinding.mccore.version.VersionMap; 9 | import net.minecraft.util.math.random.ChunkRandom; 10 | 11 | public class DeepDungeon extends Decorator { 12 | 13 | public static final VersionMap CONFIGS = new VersionMap() 14 | .add(MCVersion.v1_18, new Decorator.Config(3, 3)); 15 | 16 | public DeepDungeon(MCVersion version) { 17 | super(CONFIGS.getAsOf(version), version); 18 | } 19 | 20 | @Override 21 | public String getName() { 22 | return "dungeon"; 23 | } 24 | 25 | @Override 26 | public boolean canStart(DeepDungeon.Data data, long structureSeed, ChunkRand rand) { 27 | return true; 28 | } 29 | 30 | @Override 31 | public boolean canStart(DeepDungeon.Data data, long worldSeed, ChunkRandom rand) { 32 | super.canStart(data, worldSeed, rand); 33 | int x, y, z; 34 | 35 | for (int i = 0; i < 4; i++) { 36 | 37 | x = rand.nextInt(16); 38 | z = rand.nextInt(16); 39 | y = rand.nextInt(58)-58; 40 | 41 | if (y == data.blockY && x == data.offsetX && z == data.offsetZ) { 42 | return true; 43 | } 44 | 45 | rand.nextInt(2); 46 | rand.nextInt(2); 47 | } 48 | return false; 49 | } 50 | 51 | @Override 52 | public boolean isValidDimension(Dimension dimension) { 53 | return dimension == Dimension.OVERWORLD; 54 | } 55 | 56 | @Override 57 | public Dimension getValidDimension() { 58 | return Dimension.OVERWORLD; 59 | } 60 | 61 | @Override 62 | public boolean isValidBiome(Biome biome) { 63 | return biome != Biomes.NETHER_WASTES && biome != Biomes.SOUL_SAND_VALLEY && biome != Biomes.WARPED_FOREST 64 | && biome != Biomes.CRIMSON_FOREST && biome != Biomes.BASALT_DELTAS && biome != Biomes.END_MIDLANDS 65 | && biome != Biomes.END_HIGHLANDS && biome != Biomes.END_BARRENS && biome != Biomes.SMALL_END_ISLANDS 66 | && biome != Biomes.THE_VOID && biome == Biomes.THE_END; 67 | } 68 | 69 | public DeepDungeon.Data at(int blockX, int blockY, int blockZ, Biome biome) { 70 | return new DeepDungeon.Data(this, blockX, blockY, blockZ, biome); 71 | } 72 | 73 | public static class Data extends Decorator.Data { 74 | 75 | public final int offsetX; 76 | public final int offsetZ; 77 | public final int blockY; 78 | 79 | public Data(DeepDungeon feature, int blockX, int blockY, int blockZ, Biome biome) { 80 | super(feature, blockX >> 4, blockZ >> 4, biome); 81 | this.offsetX = blockX & 15; 82 | this.offsetZ = blockZ & 15; 83 | this.blockY = blockY; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/cracker/decorator/EmeraldOre.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.cracker.decorator; 2 | 3 | import com.seedfinding.mcbiome.biome.Biome; 4 | import com.seedfinding.mcbiome.biome.Biomes; 5 | import com.seedfinding.mccore.rand.ChunkRand; 6 | import com.seedfinding.mccore.state.Dimension; 7 | import com.seedfinding.mccore.version.MCVersion; 8 | import com.seedfinding.mccore.version.VersionMap; 9 | import net.minecraft.util.math.random.ChunkRandom; 10 | 11 | public class EmeraldOre extends Decorator { 12 | 13 | public static final VersionMap CONFIGS = new VersionMap() 14 | .add(MCVersion.v1_13, new Decorator.Config(4, 14)) 15 | .add(MCVersion.v1_16, new Decorator.Config(6, 14)) 16 | .add(MCVersion.v1_17, new Decorator.Config(6, 17)); 17 | 18 | public EmeraldOre(MCVersion version) { 19 | super(CONFIGS.getAsOf(version), version); 20 | } 21 | 22 | @Override 23 | public String getName() { 24 | return "emerald_ore"; 25 | } 26 | 27 | @Override 28 | public boolean canStart(Data data, long structureSeed, ChunkRand rand) { 29 | if (this.getVersion().isNewerThan(MCVersion.v1_17_1)) return true; 30 | super.canStart(data, structureSeed, rand); 31 | 32 | int bound = this.getVersion() == MCVersion.v1_17 ? rand.nextInt(19) + 6 : rand.nextInt(6) + 3; 33 | 34 | for (int i = 0; i < bound; i++) { 35 | int x, y, z; 36 | 37 | if (this.getVersion().isOlderThan(MCVersion.v1_15)) { 38 | x = rand.nextInt(16); 39 | y = rand.nextInt(28) + 4; 40 | z = rand.nextInt(16); 41 | } else { 42 | x = rand.nextInt(16); 43 | z = rand.nextInt(16); 44 | y = rand.nextInt(28) + 4; 45 | } 46 | 47 | if (y == data.blockY && x == data.offsetX && z == data.offsetZ) { 48 | return true; 49 | } 50 | } 51 | 52 | return false; 53 | } 54 | 55 | @Override 56 | public boolean canStart(EmeraldOre.Data data, long structureSeed, ChunkRandom rand) { 57 | return true; 58 | //super.canStart(data, structureSeed, rand); 59 | //int x, y, z; 60 | // 61 | //for (int i = 0; i < 10; i++) { 62 | // 63 | // x = rand.nextInt(16); 64 | // z = rand.nextInt(16); 65 | // y = rand.nextInt(); 66 | // 67 | // if (y == data.blockY && x == data.offsetX && z == data.offsetZ) { 68 | // return true; 69 | // } 70 | // 71 | // rand.nextInt(2); 72 | // rand.nextInt(2); 73 | //} 74 | //return false; 75 | } 76 | 77 | @Override 78 | public boolean isValidDimension(Dimension dimension) { 79 | return dimension == Dimension.OVERWORLD; 80 | } 81 | 82 | @Override 83 | public boolean isValidBiome(Biome biome) { 84 | return biome == Biomes.GRAVELLY_MOUNTAINS || biome == Biomes.MODIFIED_GRAVELLY_MOUNTAINS 85 | || biome == Biomes.MOUNTAINS || biome == Biomes.WOODED_MOUNTAINS || biome == Biomes.MOUNTAIN_EDGE; 86 | } 87 | 88 | @Override 89 | public Dimension getValidDimension() { 90 | return Dimension.OVERWORLD; 91 | } 92 | 93 | 94 | public EmeraldOre.Data at(int blockX, int blockY, int blockZ, Biome biome) { 95 | return new EmeraldOre.Data(this, blockX, blockY, blockZ, biome); 96 | } 97 | 98 | public static class Data extends Decorator.Data { 99 | public final int offsetX; 100 | public final int blockY; 101 | public final int offsetZ; 102 | 103 | public Data(EmeraldOre feature, int blockX, int blockY, int blockZ, Biome biome) { 104 | super(feature, blockX >> 4, blockZ >> 4, biome); 105 | this.offsetX = blockX & 15; 106 | this.blockY = blockY; 107 | this.offsetZ = blockZ & 15; 108 | } 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/cracker/decorator/FullFungusData.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.cracker.decorator; 2 | 3 | import com.seedfinding.latticg.reversal.DynamicProgram; 4 | import com.seedfinding.latticg.reversal.calltype.java.JavaCalls; 5 | import com.seedfinding.latticg.util.LCG; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.stream.LongStream; 10 | 11 | public class FullFungusData { 12 | 13 | 14 | public final ArrayList layerSizes = new ArrayList<>(); 15 | public final int[][][] layers; 16 | public final ArrayList vines = new ArrayList<>(); 17 | public final ArrayList bigtrunkData = new ArrayList<>(); 18 | public final int estimatedData; 19 | public boolean big; 20 | public int height; 21 | public int vineLayerSize; 22 | 23 | public FullFungusData(List layerSizes, int[][][] layers, ArrayList vines, boolean big, int height, int vineLayerSize, ArrayList bigTrunkData, int estimatedData) { 24 | this.layerSizes.addAll(layerSizes); 25 | this.layers = layers.clone(); 26 | this.vines.addAll(vines); 27 | this.big = big; 28 | this.height = height; 29 | this.vineLayerSize = vineLayerSize; 30 | this.bigtrunkData.addAll(bigTrunkData); 31 | this.estimatedData = estimatedData; 32 | } 33 | 34 | 35 | public static FullFungusData getBestFungus(List fungusList) { 36 | int data = 0; 37 | FullFungusData out = null; 38 | 39 | for (FullFungusData fungus : fungusList) { 40 | int fungusData = fungus.estimatedData; 41 | if (fungusData > data) { 42 | data = fungusData; 43 | out = fungus; 44 | } 45 | } 46 | 47 | return out; 48 | } 49 | 50 | public LongStream crackSeed() { 51 | int doppelt = 0; 52 | if (height > 7 && height % 2 == 0) { 53 | doppelt = 1; 54 | if (height > 13) { 55 | doppelt = 2; 56 | } 57 | } 58 | 59 | DynamicProgram device = DynamicProgram.create(LCG.JAVA); 60 | if (doppelt < 2) { 61 | device.skip(2); 62 | } else { 63 | device.skip(1); 64 | device.add(JavaCalls.nextInt(12).equalTo(0)); 65 | } 66 | if (big) { 67 | device.add(JavaCalls.nextFloat().betweenII(0F, 0.06F)); 68 | } else { 69 | device.skip(1); 70 | } 71 | 72 | if (big) { 73 | for (int blockdata : bigtrunkData) { 74 | if (blockdata == 0) { 75 | device.skip(1); 76 | } else if (blockdata == 1) { 77 | device.add(JavaCalls.nextFloat().betweenII(0F, 0.1F)); 78 | } 79 | } 80 | } 81 | 82 | device.skip(2); 83 | 84 | ArrayList done = new ArrayList<>(); 85 | for (int j = 3; j > 0; j--) { 86 | 87 | for (int i = 0; i < vineLayerSize * 8; i++) { 88 | if (vines.get(i) == 0 && !done.contains(i)) { 89 | device.skip(1); 90 | 91 | } else if (vines.get(i) == j) { 92 | done.add(i); 93 | device.add(JavaCalls.nextFloat().betweenII(0F, 0.15F)); 94 | 95 | } else if (!done.contains(i)) { 96 | device.skip(1); 97 | 98 | } 99 | } 100 | 101 | device.skip(1); 102 | } 103 | int relativePos; 104 | int blockType; 105 | int layer = 0; 106 | 107 | for (int size : layerSizes) { 108 | size *= 2; 109 | 110 | for (int x = 0; x <= size; x++) { 111 | 112 | boolean siteX = x == 0 || x == size; 113 | for (int z = 0; z <= size; z++) { 114 | 115 | boolean siteZ = z == 0 || z == size; 116 | 117 | relativePos = (siteX ? 1 : 0) + (siteZ ? 1 : 0); 118 | 119 | blockType = layers[layer][x][z]; 120 | 121 | generateBlock(relativePos, blockType, device); 122 | } 123 | } 124 | 125 | device.skip(1); 126 | layer++; 127 | } 128 | return device.reverse(); 129 | } 130 | 131 | private void generateBlock(int relativePos, int blockType, DynamicProgram device) { 132 | 133 | if (blockType == 3) return; 134 | switch (relativePos) { 135 | case 0: 136 | //Inside 137 | switch (blockType) { 138 | case 0: 139 | device.skip(2); 140 | break; 141 | case 1: 142 | device.skip(3); 143 | break; 144 | case 2: 145 | device.add(JavaCalls.nextFloat().betweenII(0F, 0.1F)); 146 | } 147 | break; 148 | case 1: 149 | //Wall 150 | switch (blockType) { 151 | case 0: 152 | device.skip(1); 153 | device.add(JavaCalls.nextFloat().betweenII(0.98F, 1F)); 154 | break; 155 | case 1: 156 | device.skip(3); 157 | break; 158 | case 2: 159 | device.add(JavaCalls.nextFloat().betweenII(0F, 5.0E-4F)); 160 | } 161 | break; 162 | case 2: 163 | //Corner 164 | switch (blockType) { 165 | case 0: 166 | device.skip(2); 167 | break; 168 | case 1: 169 | device.skip(3); 170 | break; 171 | case 2: 172 | device.add(JavaCalls.nextFloat().betweenII(0F, 0.01F)); 173 | } 174 | break; 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/cracker/storage/ProgressListener.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.cracker.storage; 2 | 3 | import kaptainwutax.seedcrackerX.util.Log; 4 | 5 | public class ProgressListener { 6 | 7 | protected float progress; 8 | protected int count = 0; 9 | 10 | public ProgressListener() { 11 | this(0.0F); 12 | } 13 | 14 | public ProgressListener(float progress) { 15 | this.progress = progress; 16 | } 17 | 18 | public synchronized void addPercent(float percent, boolean debug) { 19 | if ((this.count & 3) == 0 && debug) { 20 | Log.debug(Log.translate("tmachine.progress") + ": " + this.progress + "%"); 21 | } 22 | 23 | this.count++; 24 | this.progress += percent; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/cracker/storage/ScheduledSet.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.cracker.storage; 2 | 3 | import java.util.*; 4 | 5 | public class ScheduledSet implements Iterable { 6 | 7 | protected final Set baseSet; 8 | protected final Set scheduledSet; 9 | 10 | public ScheduledSet(Comparator comparator) { 11 | if (comparator != null) { 12 | this.baseSet = new TreeSet<>(comparator); 13 | } else { 14 | this.baseSet = new HashSet<>(); 15 | } 16 | 17 | this.scheduledSet = new HashSet<>(); 18 | } 19 | 20 | public synchronized void scheduleAdd(T e) { 21 | this.scheduledSet.add(e); 22 | } 23 | 24 | public synchronized void dump() { 25 | synchronized (this.baseSet) { 26 | this.baseSet.addAll(this.scheduledSet); 27 | this.scheduledSet.clear(); 28 | } 29 | } 30 | 31 | public synchronized boolean contains(T e) { 32 | return this.baseSet.contains(e) || this.scheduledSet.contains(e); 33 | } 34 | 35 | public Set getBaseSet() { 36 | return this.baseSet; 37 | } 38 | 39 | @Override 40 | public synchronized Iterator iterator() { 41 | return this.baseSet.iterator(); 42 | } 43 | 44 | public synchronized int size() { 45 | return this.baseSet.size(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/BiomeFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder; 2 | 3 | import com.seedfinding.mcbiome.biome.Biomes; 4 | import com.seedfinding.mccore.version.MCVersion; 5 | import kaptainwutax.seedcrackerX.SeedCracker; 6 | import kaptainwutax.seedcrackerX.config.Config; 7 | import kaptainwutax.seedcrackerX.cracker.BiomeData; 8 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 9 | import kaptainwutax.seedcrackerX.render.Color; 10 | import kaptainwutax.seedcrackerX.render.Cube; 11 | import kaptainwutax.seedcrackerX.util.BiomeFixer; 12 | import kaptainwutax.seedcrackerX.util.Log; 13 | import net.minecraft.util.math.BlockPos; 14 | import net.minecraft.util.math.ChunkPos; 15 | import net.minecraft.world.Heightmap; 16 | import net.minecraft.world.World; 17 | import net.minecraft.world.biome.Biome; 18 | import net.minecraft.world.dimension.DimensionType; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | public class BiomeFinder extends Finder { 24 | 25 | public BiomeFinder(World world, ChunkPos chunkPos) { 26 | super(world, chunkPos); 27 | } 28 | 29 | public static List create(World world, ChunkPos chunkPos) { 30 | List finders = new ArrayList<>(); 31 | finders.add(new BiomeFinder(world, chunkPos)); 32 | return finders; 33 | } 34 | 35 | @Override 36 | public List findInChunk() { 37 | List result = new ArrayList<>(); 38 | 39 | for (int x = 0; x < 16; x += 4) { 40 | for (int z = 0; z < 16; z += 4) { 41 | BlockPos blockPos = this.chunkPos.getStartPos().add(x, 0, z); 42 | Biome biome; 43 | if (Config.get().getVersion().isNewerOrEqualTo(MCVersion.v1_15)) { 44 | biome = this.world.getBiomeForNoiseGen(blockPos.getX() >> 2, 0, blockPos.getZ() >> 2).value(); 45 | } else { 46 | biome = this.world.getBiome(blockPos).value(); 47 | 48 | } 49 | com.seedfinding.mcbiome.biome.Biome otherBiome = BiomeFixer.swap(biome); 50 | if (otherBiome == Biomes.THE_VOID) { 51 | continue; 52 | } 53 | 54 | BiomeData data; 55 | if (Config.get().getVersion().isNewerOrEqualTo(MCVersion.v1_15)) { 56 | data = new BiomeData(otherBiome, blockPos.getX() >> 2, blockPos.getZ() >> 2); 57 | } else { 58 | data = new BiomeData(otherBiome, blockPos.getX(), blockPos.getZ()); 59 | } 60 | if (SeedCracker.get().getDataStorage().addBiomeData(data, DataAddedEvent.POKE_BIOMES)) { 61 | blockPos = this.world.getTopPosition(Heightmap.Type.WORLD_SURFACE, blockPos).down(); 62 | if (Config.get().debug) Log.warn(blockPos.toShortString() + ", " + otherBiome.getName()); 63 | result.add(blockPos); 64 | } 65 | } 66 | } 67 | result.forEach(pos -> this.renderers.add(new Cube(pos, new Color(51, 204, 128)))); 68 | 69 | return result; 70 | } 71 | 72 | @Override 73 | public boolean isValidDimension(DimensionType dimension) { 74 | return this.isOverworld(dimension); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/BlockFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder; 2 | 3 | import net.minecraft.block.Block; 4 | import net.minecraft.block.BlockState; 5 | import net.minecraft.util.math.BlockPos; 6 | import net.minecraft.util.math.ChunkPos; 7 | import net.minecraft.world.World; 8 | import net.minecraft.world.chunk.Chunk; 9 | 10 | import java.util.*; 11 | import java.util.stream.Collectors; 12 | 13 | public abstract class BlockFinder extends Finder { 14 | 15 | private final Set targetBlockStates = new HashSet<>(); 16 | protected List searchPositions = new ArrayList<>(); 17 | 18 | public BlockFinder(World world, ChunkPos chunkPos, Block block) { 19 | super(world, chunkPos); 20 | this.targetBlockStates.addAll(block.getStateManager().getStates()); 21 | } 22 | 23 | public BlockFinder(World world, ChunkPos chunkPos, BlockState... blockStates) { 24 | super(world, chunkPos); 25 | this.targetBlockStates.addAll(Arrays.stream(blockStates).collect(Collectors.toList())); 26 | } 27 | 28 | @Override 29 | public List findInChunk() { 30 | List result = new ArrayList<>(); 31 | Chunk chunk = this.world.getChunk(this.chunkPos.getStartPos()); 32 | 33 | for (BlockPos blockPos : this.searchPositions) { 34 | BlockState currentState = chunk.getBlockState(blockPos); 35 | 36 | if (this.targetBlockStates.contains(currentState)) { 37 | result.add(this.chunkPos.getStartPos().add(blockPos)); 38 | } 39 | } 40 | 41 | return result; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/BlockUpdateQueue.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder; 2 | 3 | import net.minecraft.client.MinecraftClient; 4 | import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; 5 | import net.minecraft.util.Pair; 6 | import net.minecraft.util.math.BlockPos; 7 | import net.minecraft.util.math.Direction; 8 | 9 | import java.util.ArrayList; 10 | import java.util.HashSet; 11 | import java.util.LinkedList; 12 | import java.util.Queue; 13 | 14 | public class BlockUpdateQueue { 15 | private final Queue>> blocksAndAction = new LinkedList<>(); 16 | private final HashSet alreadyChecked = new HashSet<>(); 17 | 18 | public boolean add(ArrayList blockPoses, BlockPos originPos, Thread operationAtEnd) { 19 | if (alreadyChecked.add(originPos)) { 20 | blocksAndAction.add(new Pair<>(operationAtEnd, blockPoses)); 21 | return true; 22 | } 23 | return false; 24 | } 25 | 26 | public void tick() { 27 | if (blocksAndAction.isEmpty()) return; 28 | 29 | Pair> current = blocksAndAction.peek(); 30 | ArrayList currentBlocks = current.getRight(); 31 | for (int i = 0; i < 5; i++) { 32 | if (currentBlocks.isEmpty()) { 33 | current.getLeft().start(); 34 | blocksAndAction.remove(); 35 | if (blocksAndAction.isEmpty()) { 36 | return; 37 | } else { 38 | current = blocksAndAction.peek(); 39 | currentBlocks = current.getRight(); 40 | } 41 | } 42 | if (MinecraftClient.getInstance().getNetworkHandler() == null) { 43 | blocksAndAction.clear(); 44 | return; 45 | } 46 | PlayerActionC2SPacket p = new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.ABORT_DESTROY_BLOCK, currentBlocks.remove(0), 47 | Direction.DOWN); 48 | MinecraftClient.getInstance().getNetworkHandler().sendPacket(p); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/Finder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder; 2 | 3 | import kaptainwutax.seedcrackerX.config.Config; 4 | import kaptainwutax.seedcrackerX.finder.decorator.*; 5 | import kaptainwutax.seedcrackerX.finder.decorator.ore.EmeraldOreFinder; 6 | import kaptainwutax.seedcrackerX.finder.structure.*; 7 | import kaptainwutax.seedcrackerX.render.Renderer; 8 | import kaptainwutax.seedcrackerX.util.FeatureToggle; 9 | import kaptainwutax.seedcrackerX.util.HeightContext; 10 | import net.minecraft.client.MinecraftClient; 11 | import net.minecraft.client.render.VertexConsumer; 12 | import net.minecraft.client.util.math.MatrixStack; 13 | import net.minecraft.util.math.BlockPos; 14 | import net.minecraft.util.math.ChunkPos; 15 | import net.minecraft.util.math.Vec3d; 16 | import net.minecraft.world.World; 17 | import net.minecraft.world.dimension.DimensionType; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | import java.util.function.Predicate; 23 | import java.util.stream.Collectors; 24 | 25 | public abstract class Finder { 26 | 27 | protected static final List CHUNK_POSITIONS = new ArrayList<>(); 28 | protected static final List SUB_CHUNK_POSITIONS = new ArrayList<>(); 29 | protected static HeightContext heightContext; 30 | 31 | static { 32 | for (int x = 0; x < 16; x++) { 33 | for (int z = 0; z < 16; z++) { 34 | for (int y = 0; y < 16; y++) { 35 | SUB_CHUNK_POSITIONS.add(new BlockPos(x, y, z)); 36 | } 37 | } 38 | } 39 | } 40 | 41 | protected MinecraftClient mc = MinecraftClient.getInstance(); 42 | protected List renderers = new ArrayList<>(); 43 | protected World world; 44 | protected ChunkPos chunkPos; 45 | 46 | public Finder(World world, ChunkPos chunkPos) { 47 | this.world = world; 48 | this.chunkPos = chunkPos; 49 | } 50 | 51 | public static List buildSearchPositions(List base, Predicate removeIf) { 52 | List newList = new ArrayList<>(); 53 | 54 | for (BlockPos pos : base) { 55 | if (!removeIf.test(pos)) { 56 | newList.add(pos); 57 | } 58 | } 59 | 60 | return newList; 61 | } 62 | 63 | public World getWorld() { 64 | return this.world; 65 | } 66 | 67 | public ChunkPos getChunkPos() { 68 | return this.chunkPos; 69 | } 70 | 71 | public abstract List findInChunk(); 72 | 73 | public boolean shouldRender() { 74 | DimensionType finderDim = this.world.getDimension(); 75 | DimensionType playerDim = mc.player.clientWorld.getDimension(); 76 | 77 | if (finderDim != playerDim) return false; 78 | 79 | int renderDistance = mc.options.getViewDistance().getValue() * 16 + 16; 80 | Vec3d playerPos = mc.player.getPos(); 81 | 82 | for (Renderer renderer : this.renderers) { 83 | BlockPos pos = renderer.getPos(); 84 | double distance = playerPos.squaredDistanceTo(pos.getX(), playerPos.y, pos.getZ()); 85 | if (distance <= renderDistance * renderDistance + 32) return true; 86 | } 87 | 88 | return false; 89 | } 90 | 91 | public void render(MatrixStack.Entry matrix4f, VertexConsumer vertexConsumer, Vec3d cameraPos) { 92 | this.renderers.forEach(renderer -> renderer.render(matrix4f, vertexConsumer, cameraPos)); 93 | } 94 | 95 | public boolean isUseless() { 96 | return this.renderers.isEmpty(); 97 | } 98 | 99 | public abstract boolean isValidDimension(DimensionType dimension); 100 | 101 | public boolean isOverworld(DimensionType dimension) { 102 | return dimension.effects().getPath().equals("overworld"); 103 | } 104 | 105 | public boolean isNether(DimensionType dimension) { 106 | return dimension.effects().getPath().equals("the_nether"); 107 | } 108 | 109 | public boolean isEnd(DimensionType dimension) { 110 | return dimension.effects().getPath().equals("the_end"); 111 | } 112 | 113 | public enum Category { 114 | STRUCTURES, 115 | DECORATORS, 116 | BIOMES, 117 | } 118 | 119 | public enum Type { 120 | BURIED_TREASURE(BuriedTreasureFinder::create, Category.STRUCTURES, Config.get().buriedTreasure, "finder.buriedTreasures"), 121 | DESERT_TEMPLE(DesertPyramidFinder::create, Category.STRUCTURES, Config.get().desertTemple, "finder.desertTemples"), 122 | END_CITY(EndCityFinder::create, Category.STRUCTURES, Config.get().endCity, "finder.endCities"), 123 | JUNGLE_TEMPLE(JunglePyramidFinder::create, Category.STRUCTURES, Config.get().jungleTemple, "finder.jungleTemples"), 124 | MONUMENT(MonumentFinder::create, Category.STRUCTURES, Config.get().monument, "finder.monuments"), 125 | SWAMP_HUT(SwampHutFinder::create, Category.STRUCTURES, Config.get().swampHut, "finder.swampHuts"), 126 | SHIPWRECK(ShipwreckFinder::create, Category.STRUCTURES, Config.get().shipwreck, "finder.shipwrecks"), 127 | PILLAGER_OUTPOST(OutpostFinder::create, Category.STRUCTURES, Config.get().outpost, "finder.outposts"), 128 | IGLOO(IglooFinder::create, Category.STRUCTURES, Config.get().igloo, "finder.igloo"), 129 | 130 | END_PILLARS(EndPillarsFinder::create, Category.DECORATORS, Config.get().endPillars, "finder.endPillars"), 131 | END_GATEWAY(EndGatewayFinder::create, Category.DECORATORS, Config.get().endGateway, "finder.endGateways"), 132 | DUNGEON(DungeonFinder::create, Category.DECORATORS, Config.get().dungeon, "finder.dungeons"), 133 | EMERALD_ORE(EmeraldOreFinder::create, Category.DECORATORS, Config.get().emeraldOre, "finder.emeraldOres"), 134 | DESERT_WELL(DesertWellFinder::create, Category.DECORATORS, Config.get().desertWell, "finder.desertWells"), 135 | WARPED_FUNGUS(WarpedFungusFinder::create, Category.DECORATORS, Config.get().warpedFungus, "finder.warpedFungus"), 136 | 137 | BIOME(BiomeFinder::create, Category.BIOMES, Config.get().biome, "finder.biomes"); 138 | 139 | public final FinderBuilder finderBuilder; 140 | public final String nameKey; 141 | private final Category category; 142 | public FeatureToggle enabled; 143 | 144 | Type(FinderBuilder finderBuilder, Category category, FeatureToggle enabled, String nameKey) { 145 | this.finderBuilder = finderBuilder; 146 | this.category = category; 147 | this.enabled = enabled; 148 | this.nameKey = nameKey; 149 | } 150 | 151 | public static List getForCategory(Category category) { 152 | return Arrays.stream(values()).filter(type -> type.category == category).collect(Collectors.toList()); 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/FinderBuilder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder; 2 | 3 | import net.minecraft.util.math.ChunkPos; 4 | import net.minecraft.world.World; 5 | 6 | import java.util.List; 7 | 8 | @FunctionalInterface 9 | public interface FinderBuilder { 10 | 11 | List build(World world, ChunkPos chunkPos); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/FinderControl.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Queue; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | import java.util.concurrent.ConcurrentLinkedQueue; 8 | import java.util.stream.Collectors; 9 | 10 | public class FinderControl { 11 | 12 | private final Map> activeFinders = new ConcurrentHashMap<>(); 13 | 14 | public void deleteFinders() { 15 | this.activeFinders.clear(); 16 | } 17 | 18 | public List getActiveFinders() { 19 | this.activeFinders.values().forEach(finders -> { 20 | finders.removeIf(Finder::isUseless); 21 | }); 22 | 23 | return this.activeFinders.values().stream() 24 | .flatMap(Queue::stream).collect(Collectors.toList()); 25 | } 26 | 27 | public void addFinder(Finder.Type type, Finder finder) { 28 | if (finder.isUseless()) return; 29 | 30 | if (!this.activeFinders.containsKey(type)) { 31 | this.activeFinders.put(type, new ConcurrentLinkedQueue<>()); 32 | } 33 | 34 | this.activeFinders.get(type).add(finder); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/FinderQueue.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder; 2 | 3 | import com.mojang.blaze3d.pipeline.RenderPipeline; 4 | import com.mojang.blaze3d.platform.DepthTestFunction; 5 | import kaptainwutax.seedcrackerX.config.Config; 6 | import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; 7 | import net.minecraft.client.gl.RenderPipelines; 8 | import net.minecraft.client.render.*; 9 | import net.minecraft.client.util.math.MatrixStack; 10 | import net.minecraft.util.Identifier; 11 | import net.minecraft.util.math.ChunkPos; 12 | import net.minecraft.util.math.Vec3d; 13 | import net.minecraft.world.World; 14 | 15 | import java.util.Arrays; 16 | import java.util.List; 17 | import java.util.OptionalDouble; 18 | import java.util.concurrent.ExecutorService; 19 | import java.util.concurrent.Executors; 20 | import java.util.stream.Collectors; 21 | 22 | public class FinderQueue { 23 | 24 | private final static FinderQueue INSTANCE = new FinderQueue(); 25 | public static ExecutorService SERVICE = Executors.newFixedThreadPool(5); 26 | 27 | private static final RenderPipeline LINES_NO_DEPTH_PIPELINE = RenderPipelines.register( 28 | RenderPipeline.builder(RenderPipelines.RENDERTYPE_LINES_SNIPPET) 29 | .withLocation(Identifier.of("seedcrackerx", "pipeline/lines_no_depth")) 30 | .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) 31 | .withFragmentShader(Identifier.of("seedcrackerx", "core/rendertype_lines")) 32 | .build() 33 | ); 34 | public static final RenderLayer LINES_NO_DEPTH_LAYER = RenderLayer.of("seedcrackerx_no_depth", 3 * 512, LINES_NO_DEPTH_PIPELINE, RenderLayer.MultiPhaseParameters.builder() 35 | .layering(RenderPhase.VIEW_OFFSET_Z_LAYERING) 36 | 37 | .lineWidth(new RenderPhase.LineWidth(OptionalDouble.of(2f))) 38 | .build(false)); 39 | 40 | public FinderControl finderControl = new FinderControl(); 41 | 42 | private FinderQueue() { 43 | this.clear(); 44 | } 45 | 46 | public static FinderQueue get() { 47 | return INSTANCE; 48 | } 49 | 50 | public void onChunkData(World world, ChunkPos chunkPos) { 51 | if (!Config.get().active) return; 52 | 53 | getActiveFinderTypes().forEach(type -> { 54 | SERVICE.submit(() -> { 55 | try { 56 | List finders = type.finderBuilder.build(world, chunkPos); 57 | 58 | finders.forEach(finder -> { 59 | if (finder.isValidDimension(world.getDimension())) { 60 | finder.findInChunk(); 61 | this.finderControl.addFinder(type, finder); 62 | } 63 | }); 64 | } catch (Exception e) { 65 | e.printStackTrace(); 66 | } 67 | }); 68 | }); 69 | } 70 | 71 | static { 72 | WorldRenderEvents.AFTER_TRANSLUCENT.register(context -> { 73 | context.matrixStack().push(); 74 | FinderQueue.get().renderFinders(context.matrixStack().peek(), context.consumers().getBuffer(FinderQueue.LINES_NO_DEPTH_LAYER), context.camera()); 75 | context.matrixStack().pop(); 76 | }); 77 | } 78 | 79 | public void renderFinders(MatrixStack.Entry matrix4f, VertexConsumer buffer, Camera camera) { 80 | if (Config.get().render == Config.RenderType.OFF) return; 81 | 82 | Vec3d camPos = camera.getPos(); 83 | 84 | this.finderControl.getActiveFinders().forEach(finder -> { 85 | if (finder.shouldRender()) { 86 | finder.render(matrix4f, buffer, camPos); 87 | } 88 | }); 89 | } 90 | 91 | public List getActiveFinderTypes() { 92 | return Arrays.stream(Finder.Type.values()) 93 | .filter(type -> type.enabled.get()) 94 | .collect(Collectors.toList()); 95 | } 96 | 97 | public void clear() { 98 | this.finderControl = new FinderControl(); 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/ReloadFinders.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder; 2 | 3 | import kaptainwutax.seedcrackerX.finder.decorator.EndPillarsFinder; 4 | import kaptainwutax.seedcrackerX.finder.decorator.ore.EmeraldOreFinder; 5 | import kaptainwutax.seedcrackerX.finder.structure.*; 6 | import kaptainwutax.seedcrackerX.util.HeightContext; 7 | import net.minecraft.client.MinecraftClient; 8 | import net.minecraft.util.math.BlockPos; 9 | import net.minecraft.util.math.ChunkPos; 10 | 11 | public class ReloadFinders { 12 | public MinecraftClient client = MinecraftClient.getInstance(); 13 | 14 | public static void reloadHeight(int minY, int maxY) { 15 | Finder.CHUNK_POSITIONS.clear(); 16 | for (int x = 0; x < 16; x++) { 17 | for (int z = 0; z < 16; z++) { 18 | for (int y = minY; y < maxY; y++) { 19 | Finder.CHUNK_POSITIONS.add(new BlockPos(x, y, z)); 20 | } 21 | } 22 | } 23 | Finder.heightContext = new HeightContext(minY, maxY); 24 | 25 | EmeraldOreFinder.reloadSearchPositions(); 26 | EndPillarsFinder.BedrockMarkerFinder.reloadSearchPositions(); 27 | AbstractTempleFinder.reloadSearchPositions(); 28 | BuriedTreasureFinder.reloadSearchPositions(); 29 | EndCityFinder.reloadSearchPositions(); 30 | MonumentFinder.reloadSearchPositions(); 31 | OutpostFinder.reloadSearchPositions(); 32 | IglooFinder.reloadSearchPositions(); 33 | } 34 | 35 | public void reload() { 36 | int renderdistance = client.options.getViewDistance().getValue(); 37 | 38 | int playerChunkX = (int) (Math.round(client.player.getX()) >> 4); 39 | int playerChunkZ = (int) (Math.round(client.player.getZ()) >> 4); 40 | for (int i = playerChunkX - renderdistance; i < playerChunkX + renderdistance; i++) { 41 | for (int j = playerChunkZ - renderdistance; j < playerChunkZ + renderdistance; j++) { 42 | FinderQueue.get().onChunkData(client.world, new ChunkPos(i, j)); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/decorator/DesertWellFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.decorator; 2 | 3 | import com.seedfinding.mcfeature.decorator.DesertWell; 4 | import kaptainwutax.seedcrackerX.Features; 5 | import kaptainwutax.seedcrackerX.SeedCracker; 6 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 7 | import kaptainwutax.seedcrackerX.finder.Finder; 8 | import kaptainwutax.seedcrackerX.finder.structure.PieceFinder; 9 | import kaptainwutax.seedcrackerX.render.Color; 10 | import kaptainwutax.seedcrackerX.render.Cube; 11 | import kaptainwutax.seedcrackerX.render.Cuboid; 12 | import kaptainwutax.seedcrackerX.util.BiomeFixer; 13 | import net.minecraft.block.BlockState; 14 | import net.minecraft.block.Blocks; 15 | import net.minecraft.util.math.BlockPos; 16 | import net.minecraft.util.math.ChunkPos; 17 | import net.minecraft.util.math.Direction; 18 | import net.minecraft.util.math.Vec3i; 19 | import net.minecraft.world.World; 20 | import net.minecraft.world.biome.Biome; 21 | import net.minecraft.world.dimension.DimensionType; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | public class DesertWellFinder extends PieceFinder { 27 | 28 | protected static Vec3i SIZE = new Vec3i(5, 6, 5); 29 | 30 | public DesertWellFinder(World world, ChunkPos chunkPos) { 31 | super(world, chunkPos, Direction.NORTH, SIZE); 32 | this.searchPositions = CHUNK_POSITIONS; 33 | this.buildStructure(); 34 | } 35 | 36 | public static List create(World world, ChunkPos chunkPos) { 37 | List finders = new ArrayList<>(); 38 | finders.add(new DesertWellFinder(world, chunkPos)); 39 | 40 | finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z))); 41 | finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x, chunkPos.z - 1))); 42 | finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1))); 43 | 44 | finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z))); 45 | finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x, chunkPos.z + 1))); 46 | finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z + 1))); 47 | 48 | finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1))); 49 | finders.add(new DesertWellFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z + 1))); 50 | return finders; 51 | } 52 | 53 | @Override 54 | public List findInChunk() { 55 | Biome biome = this.world.getBiomeForNoiseGen((this.chunkPos.x << 2) + 2, 0, (this.chunkPos.z << 2) + 2).value(); 56 | 57 | if (!Features.DESERT_WELL.isValidBiome(BiomeFixer.swap(biome))) { 58 | return new ArrayList<>(); 59 | } 60 | 61 | List result = super.findInChunk(); 62 | 63 | result.forEach(pos -> { 64 | pos = pos.add(2, 1, 2); 65 | 66 | DesertWell.Data data = Features.DESERT_WELL.at(pos.getX(), pos.getZ()); 67 | 68 | if (SeedCracker.get().getDataStorage().addBaseData(data, DataAddedEvent.POKE_STRUCTURES)) { 69 | this.renderers.add(new Cuboid(pos.add(-2, -1, -2), SIZE, new Color(128, 128, 255))); 70 | this.renderers.add(new Cube(pos, new Color(128, 128, 255))); 71 | } 72 | }); 73 | 74 | return result; 75 | } 76 | 77 | @Override 78 | public boolean isValidDimension(DimensionType dimension) { 79 | return this.isOverworld(dimension); 80 | } 81 | 82 | protected void buildStructure() { 83 | BlockState sandstone = Blocks.SANDSTONE.getDefaultState(); 84 | BlockState sandstoneSlab = Blocks.SANDSTONE_SLAB.getDefaultState(); 85 | BlockState water = Blocks.WATER.getDefaultState(); 86 | 87 | this.fillWithOutline(0, 0, 0, 4, 1, 4, sandstone, sandstone, false); 88 | this.fillWithOutline(1, 5, 1, 3, 5, 3, sandstoneSlab, sandstoneSlab, false); 89 | this.addBlock(sandstone, 2, 5, 2); 90 | 91 | BlockPos p1 = new BlockPos(2, 1, 2); 92 | this.addBlock(water, p1.getX(), p1.getY(), p1.getZ()); 93 | 94 | Direction.Type.HORIZONTAL.forEach(facing -> { 95 | BlockPos p2 = p1.offset(facing); 96 | this.addBlock(water, p2.getX(), p2.getY(), p2.getZ()); 97 | }); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/decorator/EndGatewayFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.decorator; 2 | 3 | import com.seedfinding.mcfeature.decorator.EndGateway; 4 | import kaptainwutax.seedcrackerX.Features; 5 | import kaptainwutax.seedcrackerX.SeedCracker; 6 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 7 | import kaptainwutax.seedcrackerX.finder.BlockFinder; 8 | import kaptainwutax.seedcrackerX.finder.Finder; 9 | import kaptainwutax.seedcrackerX.render.Color; 10 | import kaptainwutax.seedcrackerX.render.Cuboid; 11 | import kaptainwutax.seedcrackerX.util.BiomeFixer; 12 | import net.minecraft.block.BlockState; 13 | import net.minecraft.block.Blocks; 14 | import net.minecraft.util.math.BlockPos; 15 | import net.minecraft.util.math.ChunkPos; 16 | import net.minecraft.world.World; 17 | import net.minecraft.world.biome.Biome; 18 | import net.minecraft.world.dimension.DimensionType; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | public class EndGatewayFinder extends BlockFinder { 24 | 25 | public EndGatewayFinder(World world, ChunkPos chunkPos) { 26 | super(world, chunkPos, Blocks.END_GATEWAY); 27 | this.searchPositions = CHUNK_POSITIONS; 28 | } 29 | 30 | public static List create(World world, ChunkPos chunkPos) { 31 | List finders = new ArrayList<>(); 32 | finders.add(new EndGatewayFinder(world, chunkPos)); 33 | return finders; 34 | } 35 | 36 | @Override 37 | public List findInChunk() { 38 | Biome biome = this.world.getBiomeForNoiseGen((this.chunkPos.x << 2) + 2, 64, (this.chunkPos.z << 2) + 2).value(); 39 | if(!Features.END_GATEWAY.isValidBiome(BiomeFixer.swap(biome)))return new ArrayList<>(); 40 | 41 | List result = super.findInChunk(); 42 | List newResult = new ArrayList<>(); 43 | 44 | result.forEach(pos -> { 45 | int height = this.findHeight(pos); 46 | 47 | if (height >= 3 && height <= 9) { 48 | newResult.add(pos); 49 | 50 | EndGateway.Data data = Features.END_GATEWAY.at(pos.getX(), pos.getZ(), height); 51 | 52 | if (SeedCracker.get().getDataStorage().addBaseData(data, DataAddedEvent.POKE_STRUCTURES)) { 53 | this.renderers.add(new Cuboid(pos.add(-1, -2, -1), pos.add(2, 3, 2), new Color(102, 102, 210))); 54 | } 55 | } 56 | }); 57 | 58 | return newResult; 59 | } 60 | 61 | private int findHeight(BlockPos pos) { 62 | int height = 0; 63 | 64 | while (pos.getY() >= 0) { 65 | pos = pos.down(); 66 | height++; 67 | 68 | BlockState state = this.world.getBlockState(pos); 69 | 70 | //Bedrock generates below gateways. 71 | if (state.getBlock() == Blocks.BEDROCK || state.getBlock() != Blocks.END_STONE) { 72 | continue; 73 | } 74 | 75 | break; 76 | } 77 | 78 | return height - 1; 79 | } 80 | 81 | @Override 82 | public boolean isValidDimension(DimensionType dimension) { 83 | return this.isEnd(dimension); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/decorator/EndPillarsFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.decorator; 2 | 3 | import com.seedfinding.mccore.version.MCVersion; 4 | import kaptainwutax.seedcrackerX.SeedCracker; 5 | import kaptainwutax.seedcrackerX.config.Config; 6 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 7 | import kaptainwutax.seedcrackerX.cracker.PillarData; 8 | import kaptainwutax.seedcrackerX.finder.BlockFinder; 9 | import kaptainwutax.seedcrackerX.finder.Finder; 10 | import kaptainwutax.seedcrackerX.render.Color; 11 | import kaptainwutax.seedcrackerX.render.Cube; 12 | import net.minecraft.block.Blocks; 13 | import net.minecraft.util.math.BlockPos; 14 | import net.minecraft.util.math.ChunkPos; 15 | import net.minecraft.util.math.Vec3i; 16 | import net.minecraft.world.World; 17 | import net.minecraft.world.dimension.DimensionType; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | 23 | public class EndPillarsFinder extends Finder { 24 | 25 | private final boolean alreadyFound; 26 | protected BedrockMarkerFinder[] bedrockMarkers = new BedrockMarkerFinder[10]; 27 | 28 | public EndPillarsFinder(World world, ChunkPos chunkPos) { 29 | super(world, chunkPos); 30 | 31 | this.alreadyFound = !SeedCracker.get().getDataStorage().addPillarData(null, DataAddedEvent.POKE_PILLARS); 32 | if (this.alreadyFound) return; 33 | 34 | for (int i = 0; i < this.bedrockMarkers.length; i++) { 35 | double x = 42.0D * Math.cos(2.0D * (-Math.PI + (Math.PI / 10.0D) * (double) i)); 36 | double z = 42.0D * Math.sin(2.0D * (-Math.PI + (Math.PI / 10.0D) * (double) i)); 37 | if (Config.get().getVersion().isOlderThan(MCVersion.v1_14)) { 38 | x = Math.round(x); 39 | z = Math.round(z); 40 | } 41 | this.bedrockMarkers[i] = new BedrockMarkerFinder(this.world, new ChunkPos(BlockPos.ofFloored(x, 0, z)), BlockPos.ofFloored(x, 0, z)); 42 | } 43 | } 44 | 45 | public static List create(World world, ChunkPos chunkPos) { 46 | List finders = new ArrayList<>(); 47 | finders.add(new EndPillarsFinder(world, chunkPos)); 48 | return finders; 49 | } 50 | 51 | @Override 52 | public List findInChunk() { 53 | List result = new ArrayList<>(); 54 | 55 | for (BedrockMarkerFinder bedrockMarker : this.bedrockMarkers) { 56 | if (bedrockMarker == null) continue; 57 | result.addAll(bedrockMarker.findInChunk()); 58 | } 59 | 60 | if (result.size() == this.bedrockMarkers.length) { 61 | PillarData pillarData = new PillarData(result.stream().map(Vec3i::getY).collect(Collectors.toList())); 62 | 63 | if (SeedCracker.get().getDataStorage().addPillarData(pillarData, DataAddedEvent.POKE_PILLARS)) { 64 | result.forEach(pos -> this.renderers.add(new Cube(pos, new Color(128, 0, 128)))); 65 | } 66 | 67 | } 68 | 69 | return result; 70 | } 71 | 72 | @Override 73 | public boolean isValidDimension(DimensionType dimension) { 74 | return this.isEnd(dimension); 75 | } 76 | 77 | public static class BedrockMarkerFinder extends BlockFinder { 78 | 79 | protected static List SEARCH_POSITIONS; 80 | 81 | public BedrockMarkerFinder(World world, ChunkPos chunkPos, BlockPos xz) { 82 | super(world, chunkPos, Blocks.BEDROCK); 83 | this.searchPositions = SEARCH_POSITIONS; 84 | } 85 | 86 | public static void reloadSearchPositions() { 87 | SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> { 88 | if (pos.getY() < 76) return true; 89 | return pos.getY() > 76 + 3 * 10; 90 | }); 91 | } 92 | 93 | @Override 94 | public List findInChunk() { 95 | return super.findInChunk(); 96 | } 97 | 98 | @Override 99 | public boolean isValidDimension(DimensionType dimension) { 100 | return true; 101 | } 102 | 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/decorator/ore/EmeraldOreFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.decorator.ore; 2 | 3 | import kaptainwutax.seedcrackerX.Features; 4 | import kaptainwutax.seedcrackerX.SeedCracker; 5 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 6 | import kaptainwutax.seedcrackerX.cracker.decorator.EmeraldOre; 7 | import kaptainwutax.seedcrackerX.finder.BlockFinder; 8 | import kaptainwutax.seedcrackerX.finder.Finder; 9 | import kaptainwutax.seedcrackerX.render.Color; 10 | import kaptainwutax.seedcrackerX.render.Cube; 11 | import kaptainwutax.seedcrackerX.util.BiomeFixer; 12 | import net.minecraft.block.Blocks; 13 | import net.minecraft.util.math.BlockPos; 14 | import net.minecraft.util.math.ChunkPos; 15 | import net.minecraft.world.World; 16 | import net.minecraft.world.biome.Biome; 17 | import net.minecraft.world.dimension.DimensionType; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public class EmeraldOreFinder extends BlockFinder { 23 | 24 | protected static List SEARCH_POSITIONS; 25 | 26 | public EmeraldOreFinder(World world, ChunkPos chunkPos) { 27 | super(world, chunkPos, Blocks.EMERALD_ORE); 28 | this.searchPositions = SEARCH_POSITIONS; 29 | } 30 | 31 | public static void reloadSearchPositions() { 32 | SEARCH_POSITIONS = Finder.buildSearchPositions(Finder.CHUNK_POSITIONS, pos -> { 33 | if (pos.getY() < 4) return true; 34 | return pos.getY() > 28 + 4; 35 | }); 36 | } 37 | 38 | public static List create(World world, ChunkPos chunkPos) { 39 | List finders = new ArrayList<>(); 40 | finders.add(new EmeraldOreFinder(world, chunkPos)); 41 | return finders; 42 | } 43 | 44 | @Override 45 | public List findInChunk() { 46 | Biome biome = this.world.getBiomeForNoiseGen((this.chunkPos.x << 2) + 2, 0, (this.chunkPos.z << 2) + 2).value(); 47 | 48 | List result = super.findInChunk(); 49 | if (result.isEmpty()) return result; 50 | 51 | BlockPos pos = result.get(0); 52 | 53 | EmeraldOre.Data data = Features.EMERALD_ORE.at(pos.getX(), pos.getY(), pos.getZ(), BiomeFixer.swap(biome)); 54 | 55 | if (SeedCracker.get().getDataStorage().addBaseData(data, DataAddedEvent.POKE_STRUCTURES)) { 56 | this.renderers.add(new Cube(pos, new Color(0, 255, 0))); 57 | } 58 | 59 | return result; 60 | } 61 | 62 | @Override 63 | public boolean isValidDimension(DimensionType dimension) { 64 | return this.isOverworld(dimension); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/structure/AbstractTempleFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.structure; 2 | 3 | import kaptainwutax.seedcrackerX.finder.Finder; 4 | import kaptainwutax.seedcrackerX.render.Color; 5 | import kaptainwutax.seedcrackerX.render.Cube; 6 | import kaptainwutax.seedcrackerX.render.Cuboid; 7 | import net.minecraft.util.math.BlockPos; 8 | import net.minecraft.util.math.ChunkPos; 9 | import net.minecraft.util.math.Direction; 10 | import net.minecraft.util.math.Vec3i; 11 | import net.minecraft.world.World; 12 | import net.minecraft.world.biome.Biome; 13 | import net.minecraft.world.dimension.DimensionType; 14 | 15 | import java.util.ArrayList; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | public abstract class AbstractTempleFinder extends Finder { 21 | 22 | protected static List SEARCH_POSITIONS; 23 | protected final Vec3i size; 24 | protected List finders = new ArrayList<>(); 25 | 26 | public AbstractTempleFinder(World world, ChunkPos chunkPos, Vec3i size) { 27 | super(world, chunkPos); 28 | 29 | Direction.Type.HORIZONTAL.forEach(direction -> { 30 | PieceFinder finder = new PieceFinder(world, chunkPos, direction, size); 31 | 32 | finder.searchPositions = SEARCH_POSITIONS; 33 | 34 | buildStructure(finder); 35 | this.finders.add(finder); 36 | }); 37 | 38 | this.size = size; 39 | } 40 | 41 | public static void reloadSearchPositions() { 42 | SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> { 43 | if (pos.getX() != 0) return true; 44 | if (pos.getY() < 0) return true; 45 | if (pos.getY() > 200) return true; 46 | return pos.getZ() != 0; 47 | }); 48 | } 49 | 50 | public List findInChunkPiece(PieceFinder pieceFinder) { 51 | Biome biome = this.world.getBiomeForNoiseGen((this.chunkPos.x << 2) + 2, 64, (this.chunkPos.z << 2) + 2).value(); 52 | 53 | if (!isValidBiome(biome)) { 54 | return new ArrayList<>(); 55 | } 56 | 57 | return pieceFinder.findInChunk(); 58 | } 59 | 60 | protected abstract boolean isValidBiome(Biome biome); 61 | 62 | public void addRenderers(PieceFinder pieceFinder, BlockPos origin, Color color) { 63 | this.renderers.add(new Cuboid(origin, pieceFinder.getLayout(), color)); 64 | BlockPos chunkStart = new BlockPos(origin.getX() & -16, origin.getY(), origin.getZ() & -16); 65 | this.renderers.add(new Cube(chunkStart, color)); 66 | } 67 | 68 | public Map> findInChunkPieces() { 69 | Map> result = new HashMap<>(); 70 | 71 | this.finders.forEach(pieceFinder -> { 72 | result.put(pieceFinder, this.findInChunkPiece(pieceFinder)); 73 | }); 74 | 75 | return result; 76 | } 77 | 78 | public abstract void buildStructure(PieceFinder finder); 79 | 80 | @Override 81 | public boolean isValidDimension(DimensionType dimension) { 82 | return this.isOverworld(dimension); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/structure/BuriedTreasureFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.structure; 2 | 3 | import com.seedfinding.mcfeature.structure.RegionStructure; 4 | import kaptainwutax.seedcrackerX.Features; 5 | import kaptainwutax.seedcrackerX.SeedCracker; 6 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 7 | import kaptainwutax.seedcrackerX.finder.BlockFinder; 8 | import kaptainwutax.seedcrackerX.finder.Finder; 9 | import kaptainwutax.seedcrackerX.render.Color; 10 | import kaptainwutax.seedcrackerX.render.Cube; 11 | import kaptainwutax.seedcrackerX.util.BiomeFixer; 12 | import net.minecraft.block.BlockState; 13 | import net.minecraft.block.Blocks; 14 | import net.minecraft.block.ChestBlock; 15 | import net.minecraft.util.math.BlockPos; 16 | import net.minecraft.util.math.ChunkPos; 17 | import net.minecraft.world.World; 18 | import net.minecraft.world.biome.Biome; 19 | import net.minecraft.world.dimension.DimensionType; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | public class BuriedTreasureFinder extends BlockFinder { 25 | 26 | protected static final List CHEST_HOLDERS = new ArrayList<>(); 27 | protected static List SEARCH_POSITIONS; 28 | 29 | static { 30 | CHEST_HOLDERS.add(Blocks.SANDSTONE.getDefaultState()); 31 | CHEST_HOLDERS.add(Blocks.STONE.getDefaultState()); 32 | CHEST_HOLDERS.add(Blocks.ANDESITE.getDefaultState()); 33 | CHEST_HOLDERS.add(Blocks.GRANITE.getDefaultState()); 34 | CHEST_HOLDERS.add(Blocks.DIORITE.getDefaultState()); 35 | 36 | //Population can turn stone, andesite, granite and diorite into ores... 37 | CHEST_HOLDERS.add(Blocks.COAL_ORE.getDefaultState()); 38 | CHEST_HOLDERS.add(Blocks.IRON_ORE.getDefaultState()); 39 | CHEST_HOLDERS.add(Blocks.GOLD_ORE.getDefaultState()); 40 | 41 | //Ocean can turn stone into gravel. 42 | CHEST_HOLDERS.add(Blocks.GRAVEL.getDefaultState()); 43 | } 44 | 45 | public BuriedTreasureFinder(World world, ChunkPos chunkPos) { 46 | super(world, chunkPos, Blocks.CHEST); 47 | this.searchPositions = SEARCH_POSITIONS; 48 | } 49 | 50 | public static void reloadSearchPositions() { 51 | SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> { 52 | //Buried treasure chests always generate at (9, 9) within a chunk. 53 | int localX = pos.getX() & 15; 54 | int localZ = pos.getZ() & 15; 55 | if (localX != 9 || localZ != 9) return true; 56 | return pos.getY() > 90 && pos.getY() < 0; 57 | }); 58 | } 59 | 60 | public static List create(World world, ChunkPos chunkPos) { 61 | List finders = new ArrayList<>(); 62 | finders.add(new BuriedTreasureFinder(world, chunkPos)); 63 | return finders; 64 | } 65 | 66 | @Override 67 | public List findInChunk() { 68 | 69 | Biome biome = this.world.getBiomeForNoiseGen((this.chunkPos.x << 2) + 2, 64, (this.chunkPos.z << 2) + 2).value(); 70 | if (!Features.BURIED_TREASURE.isValidBiome(BiomeFixer.swap(biome))) return new ArrayList<>(); 71 | 72 | List result = super.findInChunk(); 73 | 74 | result.removeIf(pos -> { 75 | BlockState chest = world.getBlockState(pos); 76 | if (chest.get(ChestBlock.WATERLOGGED)) return true; 77 | 78 | BlockState chestHolder = world.getBlockState(pos.down()); 79 | return !CHEST_HOLDERS.contains(chestHolder); 80 | }); 81 | 82 | result.forEach(pos -> { 83 | RegionStructure.Data data = Features.BURIED_TREASURE.at(this.chunkPos.x, this.chunkPos.z); 84 | 85 | if (SeedCracker.get().getDataStorage().addBaseData(data, DataAddedEvent.POKE_STRUCTURES)) { 86 | this.renderers.add(new Cube(pos, new Color(255, 255, 0))); 87 | } 88 | }); 89 | 90 | return result; 91 | } 92 | 93 | @Override 94 | public boolean isValidDimension(DimensionType dimension) { 95 | return this.isOverworld(dimension); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/structure/EndCityFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.structure; 2 | 3 | import com.seedfinding.mccore.version.MCVersion; 4 | import com.seedfinding.mcfeature.structure.RegionStructure; 5 | import kaptainwutax.seedcrackerX.Features; 6 | import kaptainwutax.seedcrackerX.SeedCracker; 7 | import kaptainwutax.seedcrackerX.config.Config; 8 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 9 | import kaptainwutax.seedcrackerX.finder.Finder; 10 | import kaptainwutax.seedcrackerX.render.Color; 11 | import kaptainwutax.seedcrackerX.render.Cube; 12 | import kaptainwutax.seedcrackerX.render.Cuboid; 13 | import kaptainwutax.seedcrackerX.util.BiomeFixer; 14 | import net.minecraft.block.BlockState; 15 | import net.minecraft.block.Blocks; 16 | import net.minecraft.util.math.BlockPos; 17 | import net.minecraft.util.math.ChunkPos; 18 | import net.minecraft.util.math.Direction; 19 | import net.minecraft.util.math.Vec3i; 20 | import net.minecraft.world.World; 21 | import net.minecraft.world.biome.Biome; 22 | import net.minecraft.world.dimension.DimensionType; 23 | 24 | import java.util.ArrayList; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | public class EndCityFinder extends Finder { 30 | 31 | protected static List SEARCH_POSITIONS; 32 | protected final Vec3i size = new Vec3i(8, 4, 8); 33 | protected List finders = new ArrayList<>(); 34 | 35 | public EndCityFinder(World world, ChunkPos chunkPos) { 36 | super(world, chunkPos); 37 | 38 | Direction.Type.HORIZONTAL.forEach(direction -> { 39 | PieceFinder finder = new PieceFinder(world, chunkPos, direction, size); 40 | 41 | finder.searchPositions = SEARCH_POSITIONS; 42 | 43 | buildStructure(finder); 44 | this.finders.add(finder); 45 | }); 46 | } 47 | 48 | public static void reloadSearchPositions() { 49 | SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> pos.getY() > 90 && pos.getY() < 40); 50 | } 51 | 52 | public static List create(World world, ChunkPos chunkPos) { 53 | List finders = new ArrayList<>(); 54 | finders.add(new EndCityFinder(world, chunkPos)); 55 | finders.add(new EndCityFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z))); 56 | finders.add(new EndCityFinder(world, new ChunkPos(chunkPos.x, chunkPos.z - 1))); 57 | finders.add(new EndCityFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1))); 58 | return finders; 59 | } 60 | 61 | private void buildStructure(PieceFinder finder) { 62 | BlockState air = Blocks.AIR.getDefaultState(); 63 | BlockState endstoneBricks = Blocks.END_STONE_BRICKS.getDefaultState(); 64 | BlockState purpur = Blocks.PURPUR_BLOCK.getDefaultState(); 65 | BlockState purpurPillar = Blocks.PURPUR_PILLAR.getDefaultState(); 66 | BlockState purpleGlass = Blocks.MAGENTA_STAINED_GLASS.getDefaultState(); 67 | 68 | //Walls 69 | finder.fillWithOutline(0, 0, 0, 7, 4, 7, endstoneBricks, null, false); 70 | 71 | //Wall sides 72 | finder.fillWithOutline(0, 0, 0, 0, 3, 0, purpurPillar, purpurPillar, false); 73 | finder.fillWithOutline(7, 0, 0, 7, 3, 0, purpurPillar, purpurPillar, false); 74 | finder.fillWithOutline(0, 0, 7, 0, 3, 7, purpurPillar, purpurPillar, false); 75 | finder.fillWithOutline(7, 0, 7, 7, 3, 7, purpurPillar, purpurPillar, false); 76 | 77 | //Floor 78 | finder.fillWithOutline(0, 0, 0, 7, 0, 7, purpur, purpur, false); 79 | 80 | //Doorway 81 | finder.fillWithOutline(3, 1, 0, 4, 3, 0, air, air, false); 82 | 83 | //Windows 84 | finder.fillWithOutline(0, 2, 2, 0, 3, 2, purpleGlass, purpleGlass, false); 85 | finder.fillWithOutline(0, 2, 5, 0, 3, 5, purpleGlass, purpleGlass, false); 86 | finder.fillWithOutline(7, 2, 2, 7, 3, 2, purpleGlass, purpleGlass, false); 87 | finder.fillWithOutline(7, 2, 5, 7, 3, 5, purpleGlass, purpleGlass, false); 88 | } 89 | 90 | @Override 91 | public List findInChunk() { 92 | Biome biome = this.world.getBiomeForNoiseGen((this.chunkPos.x << 2) + 2, 64, (this.chunkPos.z << 2) + 2).value(); 93 | if (!Features.END_CITY.isValidBiome(BiomeFixer.swap(biome))) return new ArrayList<>(); 94 | 95 | Map> result = this.findInChunkPieces(); 96 | List combinedResult = new ArrayList<>(); 97 | 98 | result.forEach((pieceFinder, positions) -> { 99 | positions.removeIf(pos -> { 100 | //Figure this out, it's not a trivial task. 101 | return false; 102 | }); 103 | 104 | combinedResult.addAll(positions); 105 | 106 | positions.forEach(pos -> { 107 | //minecraft 1.19 moved end citys by 1 block reeeeeeeee 108 | if (Config.get().getVersion().isNewerOrEqualTo(MCVersion.v1_19)) { 109 | BlockPos posFix = pos.add(1, 0, 1); 110 | RegionStructure.Data data = Features.END_CITY.at(posFix.getX()>>4, posFix.getZ()>>4); 111 | 112 | if (SeedCracker.get().getDataStorage().addBaseData(data, DataAddedEvent.POKE_STRUCTURES)) { 113 | this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Color(153, 0, 153))); 114 | this.renderers.add(new Cube(posFix, new Color(153, 0, 153))); 115 | } 116 | } else { 117 | RegionStructure.Data data = Features.END_CITY.at(this.chunkPos.x, this.chunkPos.z); 118 | 119 | if (SeedCracker.get().getDataStorage().addBaseData(data, DataAddedEvent.POKE_STRUCTURES)) { 120 | this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Color(153, 0, 153))); 121 | this.renderers.add(new Cube(pos, new Color(153, 0, 153))); 122 | } 123 | } 124 | }); 125 | }); 126 | 127 | return combinedResult; 128 | } 129 | 130 | public Map> findInChunkPieces() { 131 | Map> result = new HashMap<>(); 132 | 133 | this.finders.forEach(pieceFinder -> { 134 | result.put(pieceFinder, pieceFinder.findInChunk()); 135 | }); 136 | 137 | return result; 138 | } 139 | 140 | @Override 141 | public boolean isValidDimension(DimensionType dimension) { 142 | return this.isEnd(dimension); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/structure/IglooFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.structure; 2 | 3 | import com.seedfinding.mcfeature.structure.RegionStructure; 4 | import kaptainwutax.seedcrackerX.Features; 5 | import kaptainwutax.seedcrackerX.SeedCracker; 6 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 7 | import kaptainwutax.seedcrackerX.finder.Finder; 8 | import kaptainwutax.seedcrackerX.render.Color; 9 | import kaptainwutax.seedcrackerX.render.Cube; 10 | import kaptainwutax.seedcrackerX.render.Cuboid; 11 | import net.minecraft.block.BlockState; 12 | import net.minecraft.block.Blocks; 13 | import net.minecraft.util.math.BlockPos; 14 | import net.minecraft.util.math.ChunkPos; 15 | import net.minecraft.util.math.Direction; 16 | import net.minecraft.util.math.Vec3i; 17 | import net.minecraft.world.World; 18 | import net.minecraft.world.dimension.DimensionType; 19 | 20 | import java.util.ArrayList; 21 | import java.util.HashMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | public class IglooFinder extends Finder { 26 | 27 | protected static Map> SEARCH_POSITIONS; 28 | protected static final Vec3i size = new Vec3i(7, 5, 8); 29 | protected List finders = new ArrayList<>(); 30 | 31 | public IglooFinder(World world, ChunkPos chunkPos) { 32 | super(world, chunkPos); 33 | 34 | Direction.Type.HORIZONTAL.forEach(direction -> { 35 | JigsawFinder finder = new JigsawFinder(world, chunkPos, direction, size); 36 | 37 | finder.searchPositions = SEARCH_POSITIONS.get(direction); 38 | //finder.setDebug(); 39 | buildStructure(finder); 40 | this.finders.add(finder); 41 | }); 42 | } 43 | 44 | public static void reloadSearchPositions() { 45 | SEARCH_POSITIONS = JigsawFinder.getSearchPositions(3, 5,0,0, size); 46 | } 47 | 48 | 49 | @Override 50 | public List findInChunk() { 51 | Map> result = this.findInChunkPieces(); 52 | List combinedResult = new ArrayList<>(); 53 | 54 | result.forEach((pieceFinder, positions) -> { 55 | 56 | combinedResult.addAll(positions); 57 | 58 | positions.forEach(pos -> { 59 | RegionStructure.Data data = Features.IGLOO.at(this.chunkPos.x, this.chunkPos.z); 60 | 61 | if (SeedCracker.get().getDataStorage().addBaseData(data, DataAddedEvent.POKE_LIFTING)) { 62 | this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Color(176, 207, 252))); 63 | this.renderers.add(new Cube(chunkPos.getStartPos().add(0, pos.getY(), 0), new Color(176, 207, 252))); 64 | } 65 | }); 66 | }); 67 | 68 | return combinedResult; 69 | } 70 | 71 | public Map> findInChunkPieces() { 72 | Map> result = new HashMap<>(); 73 | 74 | this.finders.forEach(pieceFinder -> { 75 | result.put(pieceFinder, pieceFinder.findInChunk()); 76 | }); 77 | 78 | return result; 79 | } 80 | 81 | public void buildStructure(JigsawFinder finder) { 82 | BlockState snow = Blocks.SNOW_BLOCK.getDefaultState(); 83 | BlockState ice = Blocks.ICE.getDefaultState(); 84 | BlockState workBench = Blocks.CRAFTING_TABLE.getDefaultState(); 85 | 86 | finder.addBlock(workBench, 1, 1, 5); 87 | for(int y = 0; y < 3; y++) { 88 | finder.addBlock(snow, 2, y, 0); 89 | finder.addBlock(snow, 2, y, 1); 90 | finder.addBlock(snow, 1, y, 2); 91 | finder.addBlock(snow, 0, y, 3); 92 | finder.addBlock(snow, 0, y, 4); 93 | finder.addBlock(ice, 0, 1, 4); 94 | finder.addBlock(snow, 0, y, 5); 95 | finder.addBlock(snow, 1, y, 6); 96 | finder.addBlock(snow, 2, y, 7); 97 | 98 | finder.addBlock(snow, 3, y, 7); 99 | 100 | finder.addBlock(snow, 4, y, 0); 101 | finder.addBlock(snow, 4, y, 1); 102 | finder.addBlock(snow, 5, y, 2); 103 | finder.addBlock(snow, 6, y, 3); 104 | finder.addBlock(snow, 6, y, 4); 105 | finder.addBlock(ice, 6, 1, 4); 106 | finder.addBlock(snow, 6, y, 5); 107 | finder.addBlock(snow, 5, y, 6); 108 | finder.addBlock(snow, 4, y, 7); 109 | } 110 | } 111 | 112 | @Override 113 | public boolean isValidDimension(DimensionType dimension) { 114 | return this.isOverworld(dimension); 115 | } 116 | 117 | public static List create(World world, ChunkPos chunkPos) { 118 | List finders = new ArrayList<>(); 119 | finders.add(new IglooFinder(world, chunkPos)); 120 | finders.add(new IglooFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z))); 121 | return finders; 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/structure/JigsawFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.structure; 2 | 3 | import net.minecraft.util.BlockMirror; 4 | import net.minecraft.util.BlockRotation; 5 | import net.minecraft.util.math.*; 6 | import net.minecraft.world.World; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | public class JigsawFinder extends PieceFinder { 14 | public JigsawFinder(World world, ChunkPos chunkPos, Direction facing, Vec3i size) { 15 | super(world, chunkPos, facing, size); 16 | } 17 | 18 | public static Map> getSearchPositions(int xRotation, int zRotation, int xOffset, int zOffset, Vec3i size) { 19 | Map> positions = new HashMap<>(); 20 | 21 | for(Direction direction : Direction.Type.HORIZONTAL) { 22 | positions.put(direction, new ArrayList<>()); 23 | //this was painful and my hope is to never do it again 24 | int x = switch (direction) { 25 | case EAST -> xRotation-size.getZ()+1+zRotation-zOffset; 26 | case SOUTH -> xRotation-size.getX()+1+xRotation-xOffset; 27 | case WEST -> xRotation-zRotation+zOffset; 28 | default -> xOffset; 29 | }; 30 | int z = switch (direction) { 31 | case EAST -> zRotation-xRotation+xOffset; 32 | case SOUTH -> zRotation-size.getZ()+1+zRotation-zOffset; 33 | case WEST -> zRotation-size.getX()+1+xRotation-xOffset; 34 | default -> zOffset; 35 | }; 36 | if (x >= 0 && x < 16 && z >= 0 && z < 16 ) { 37 | int startIndex = heightContext.getHeight()*x*16+heightContext.getHeight()*z; 38 | for (int y = 0; y < heightContext.getHeight(); y++) { 39 | positions.get(direction).add(CHUNK_POSITIONS.get(y+startIndex)); 40 | } 41 | } else { 42 | for (int y = heightContext.getBottomY(); y < heightContext.getTopY(); y++) { 43 | positions.get(direction).add(new BlockPos(x, y, z)); 44 | } 45 | } 46 | } 47 | return positions; 48 | } 49 | 50 | 51 | @Override 52 | public void setOrientation(Direction facing) { 53 | this.facing = facing; 54 | this.mirror = BlockMirror.NONE; 55 | if (facing == null) { 56 | this.rotation = BlockRotation.NONE; 57 | } else { 58 | switch (facing) { 59 | case SOUTH -> this.rotation = BlockRotation.CLOCKWISE_180; 60 | case WEST -> this.rotation = BlockRotation.COUNTERCLOCKWISE_90; 61 | case EAST -> this.rotation = BlockRotation.CLOCKWISE_90; 62 | default -> this.rotation = BlockRotation.NONE; 63 | } 64 | } 65 | } 66 | 67 | @Override 68 | protected int applyXTransform(int x, int z) { 69 | if (this.facing == null) { 70 | return x; 71 | } else { 72 | return switch (this.facing) { 73 | case EAST -> -z + this.getLayout().getX()-1; 74 | case SOUTH -> -x + this.getLayout().getX()-1; 75 | case WEST -> z; 76 | 77 | default -> x; 78 | }; 79 | } 80 | } 81 | 82 | @Override 83 | protected int applyZTransform(int x, int z) { 84 | if (this.facing == null) { 85 | return z; 86 | } else { 87 | return switch (this.facing) { 88 | case EAST -> x; 89 | case SOUTH -> -z + this.getLayout().getZ()-1; 90 | case WEST -> -x + this.getLayout().getZ()-1; 91 | 92 | default -> z; 93 | }; 94 | } 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/structure/MonumentFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.structure; 2 | 3 | import com.seedfinding.mcfeature.structure.RegionStructure; 4 | import kaptainwutax.seedcrackerX.Features; 5 | import kaptainwutax.seedcrackerX.SeedCracker; 6 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 7 | import kaptainwutax.seedcrackerX.finder.Finder; 8 | import kaptainwutax.seedcrackerX.render.Color; 9 | import kaptainwutax.seedcrackerX.render.Cube; 10 | import kaptainwutax.seedcrackerX.render.Cuboid; 11 | import kaptainwutax.seedcrackerX.util.BiomeFixer; 12 | import net.minecraft.block.BlockState; 13 | import net.minecraft.block.Blocks; 14 | import net.minecraft.util.math.BlockPos; 15 | import net.minecraft.util.math.ChunkPos; 16 | import net.minecraft.util.math.Direction; 17 | import net.minecraft.util.math.Vec3i; 18 | import net.minecraft.world.World; 19 | import net.minecraft.world.biome.Biome; 20 | import net.minecraft.world.dimension.DimensionType; 21 | 22 | import java.util.ArrayList; 23 | import java.util.HashMap; 24 | import java.util.List; 25 | import java.util.Map; 26 | 27 | public class MonumentFinder extends Finder { 28 | 29 | protected static List SEARCH_POSITIONS; 30 | protected final Vec3i size = new Vec3i(8, 5, 8); 31 | protected List finders = new ArrayList<>(); 32 | 33 | public MonumentFinder(World world, ChunkPos chunkPos) { 34 | super(world, chunkPos); 35 | 36 | PieceFinder finder = new PieceFinder(world, chunkPos, Direction.NORTH, size); 37 | 38 | finder.searchPositions = SEARCH_POSITIONS; 39 | 40 | buildStructure(finder); 41 | this.finders.add(finder); 42 | } 43 | 44 | public static void reloadSearchPositions() { 45 | SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> pos.getY() != 56); 46 | } 47 | 48 | public static List create(World world, ChunkPos chunkPos) { 49 | List finders = new ArrayList<>(); 50 | finders.add(new MonumentFinder(world, chunkPos)); 51 | finders.add(new MonumentFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z))); 52 | finders.add(new MonumentFinder(world, new ChunkPos(chunkPos.x, chunkPos.z - 1))); 53 | finders.add(new MonumentFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1))); 54 | return finders; 55 | } 56 | 57 | @Override 58 | public List findInChunk() { 59 | Biome biome = this.world.getBiomeForNoiseGen((this.chunkPos.x << 2) + 2, 64, (this.chunkPos.z << 2) + 2).value(); 60 | if (BiomeFixer.swap(biome).getCategory() != com.seedfinding.mcbiome.biome.Biome.Category.OCEAN) return new ArrayList<>(); 61 | Map> result = this.findInChunkPieces(); 62 | List combinedResult = new ArrayList<>(); 63 | 64 | result.forEach((pieceFinder, positions) -> { 65 | positions.removeIf(pos -> { 66 | //Figure this out, it's not a trivial task. 67 | return false; 68 | }); 69 | 70 | combinedResult.addAll(positions); 71 | 72 | positions.forEach(pos -> { 73 | ChunkPos monumentStart = new ChunkPos(this.chunkPos.x + 1, this.chunkPos.z + 1); 74 | RegionStructure.Data data = Features.MONUMENT.at(monumentStart.x, monumentStart.z); 75 | 76 | if (SeedCracker.get().getDataStorage().addBaseData(data, DataAddedEvent.POKE_STRUCTURES)) { 77 | this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Color(0, 0, 255))); 78 | this.renderers.add(new Cube(monumentStart.getStartPos().add(0, pos.getY(), 0), new Color(0, 0, 255))); 79 | } 80 | }); 81 | }); 82 | 83 | return combinedResult; 84 | } 85 | 86 | public Map> findInChunkPieces() { 87 | Map> result = new HashMap<>(); 88 | 89 | this.finders.forEach(pieceFinder -> { 90 | result.put(pieceFinder, pieceFinder.findInChunk()); 91 | }); 92 | 93 | return result; 94 | } 95 | 96 | @Override 97 | public boolean isValidDimension(DimensionType dimension) { 98 | return this.isOverworld(dimension); 99 | } 100 | 101 | public void buildStructure(PieceFinder finder) { 102 | BlockState prismarine = Blocks.PRISMARINE.getDefaultState(); 103 | BlockState prismarineBricks = Blocks.PRISMARINE_BRICKS.getDefaultState(); 104 | BlockState darkPrismarine = Blocks.DARK_PRISMARINE.getDefaultState(); 105 | BlockState seaLantern = Blocks.SEA_LANTERN.getDefaultState(); 106 | BlockState water = Blocks.WATER.getDefaultState(); 107 | 108 | //4 bottom pillars. 109 | for (int i = 0; i < 4; i++) { 110 | int x = i >= 2 ? 7 : 0; 111 | int z = i % 2 == 0 ? 0 : 7; 112 | 113 | for (int y = 0; y < 3; y++) { 114 | finder.addBlock(prismarineBricks, x, y, z); 115 | } 116 | } 117 | 118 | //First bend. 119 | for (int i = 0; i < 4; i++) { 120 | int x = i >= 2 ? 6 : 1; 121 | int z = i % 2 == 0 ? 1 : 6; 122 | finder.addBlock(prismarineBricks, x, 3, z); 123 | } 124 | 125 | //Prismarine ring. 126 | for (int x = 2; x <= 5; x++) { 127 | for (int z = 2; z <= 5; z++) { 128 | if (x == 2 || x == 5 || z == 2 || z == 5) { 129 | finder.addBlock(prismarine, x, 4, z); 130 | } 131 | } 132 | } 133 | 134 | //Second bend. 135 | for (int i = 0; i < 4; i++) { 136 | int x = i >= 2 ? 5 : 2; 137 | int z = i % 2 == 0 ? 2 : 5; 138 | finder.addBlock(prismarineBricks, x, 4, z); 139 | finder.addBlock(seaLantern, x, 3, z); 140 | } 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/structure/OutpostFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.structure; 2 | 3 | import com.seedfinding.mcfeature.structure.RegionStructure; 4 | import kaptainwutax.seedcrackerX.Features; 5 | import kaptainwutax.seedcrackerX.SeedCracker; 6 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 7 | import kaptainwutax.seedcrackerX.finder.Finder; 8 | import kaptainwutax.seedcrackerX.render.Color; 9 | import kaptainwutax.seedcrackerX.render.Cube; 10 | import kaptainwutax.seedcrackerX.render.Cuboid; 11 | import kaptainwutax.seedcrackerX.util.BiomeFixer; 12 | import net.minecraft.block.BlockState; 13 | import net.minecraft.block.Blocks; 14 | import net.minecraft.util.math.BlockPos; 15 | import net.minecraft.util.math.ChunkPos; 16 | import net.minecraft.util.math.Direction; 17 | import net.minecraft.util.math.Vec3i; 18 | import net.minecraft.world.World; 19 | import net.minecraft.world.biome.Biome; 20 | import net.minecraft.world.dimension.DimensionType; 21 | 22 | import java.util.ArrayList; 23 | import java.util.HashMap; 24 | import java.util.List; 25 | import java.util.Map; 26 | 27 | public class OutpostFinder extends Finder { 28 | 29 | protected static Map> SEARCH_POSITIONS; 30 | protected static final Vec3i size = new Vec3i(15, 21, 15); 31 | protected List finders = new ArrayList<>(); 32 | 33 | public OutpostFinder(World world, ChunkPos chunkPos) { 34 | super(world, chunkPos); 35 | 36 | Direction.Type.HORIZONTAL.forEach(direction -> { 37 | JigsawFinder finder = new JigsawFinder(world, chunkPos, direction, size); 38 | 39 | finder.searchPositions = SEARCH_POSITIONS.get(direction); 40 | 41 | buildStructure(finder); 42 | this.finders.add(finder); 43 | }); 44 | } 45 | 46 | public static void reloadSearchPositions() { 47 | SEARCH_POSITIONS = JigsawFinder.getSearchPositions(0, 0,0,0, size); 48 | Map> additional = JigsawFinder.getSearchPositions(0, 0,1,0, size); 49 | for(Direction direction : Direction.Type.HORIZONTAL) { 50 | SEARCH_POSITIONS.get(direction).addAll(additional.get(direction)); 51 | } 52 | 53 | } 54 | 55 | public static List create(World world, ChunkPos chunkPos) { 56 | List finders = new ArrayList<>(); 57 | finders.add(new OutpostFinder(world, chunkPos)); 58 | finders.add(new OutpostFinder(world, new ChunkPos(chunkPos.x, chunkPos.z + 1))); 59 | finders.add(new OutpostFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z))); 60 | finders.add(new OutpostFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z + 1))); 61 | return finders; 62 | } 63 | 64 | private void buildStructure(JigsawFinder finder) { 65 | BlockState chest = Blocks.CHEST.getDefaultState(); 66 | BlockState birchwood = Blocks.BIRCH_PLANKS.getDefaultState(); 67 | 68 | finder.addBlock(chest, 9, 14, 10); 69 | 70 | finder.fillWithOutline(4, 0, 4, 10, 0, 10, birchwood, birchwood, false); 71 | } 72 | 73 | @Override 74 | public List findInChunk() { 75 | Biome biome = this.world.getBiomeForNoiseGen((this.chunkPos.x << 2) + 2, 64, (this.chunkPos.z << 2) + 2).value(); 76 | if (!Features.PILLAGER_OUTPOST.isValidBiome(BiomeFixer.swap(biome))) return new ArrayList<>(); 77 | 78 | Map> result = this.findInChunkPieces(); 79 | List combinedResult = new ArrayList<>(); 80 | 81 | result.forEach((pieceFinder, positions) -> { 82 | 83 | combinedResult.addAll(positions); 84 | 85 | positions.forEach(pos -> { 86 | RegionStructure.Data data = Features.PILLAGER_OUTPOST.at(this.chunkPos.x, this.chunkPos.z); 87 | 88 | if (SeedCracker.get().getDataStorage().addBaseData(data, DataAddedEvent.POKE_LIFTING)) { 89 | this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Color(170, 84, 3))); 90 | this.renderers.add(new Cube(chunkPos.getStartPos().add(0, pos.getY(), 0), new Color(170, 84, 3))); 91 | } 92 | }); 93 | }); 94 | 95 | return combinedResult; 96 | } 97 | 98 | public Map> findInChunkPieces() { 99 | Map> result = new HashMap<>(); 100 | 101 | this.finders.forEach(pieceFinder -> { 102 | result.put(pieceFinder, pieceFinder.findInChunk()); 103 | }); 104 | 105 | return result; 106 | } 107 | 108 | @Override 109 | public boolean isValidDimension(DimensionType dimension) { 110 | return this.isOverworld(dimension); 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/finder/structure/SwampHutFinder.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.finder.structure; 2 | 3 | import com.seedfinding.mcfeature.structure.RegionStructure; 4 | import kaptainwutax.seedcrackerX.Features; 5 | import kaptainwutax.seedcrackerX.SeedCracker; 6 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 7 | import kaptainwutax.seedcrackerX.finder.Finder; 8 | import kaptainwutax.seedcrackerX.render.Color; 9 | import kaptainwutax.seedcrackerX.util.BiomeFixer; 10 | import net.minecraft.block.BlockState; 11 | import net.minecraft.block.Blocks; 12 | import net.minecraft.block.StairsBlock; 13 | import net.minecraft.block.enums.StairShape; 14 | import net.minecraft.util.math.BlockPos; 15 | import net.minecraft.util.math.ChunkPos; 16 | import net.minecraft.util.math.Direction; 17 | import net.minecraft.util.math.Vec3i; 18 | import net.minecraft.world.World; 19 | import net.minecraft.world.biome.Biome; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | public class SwampHutFinder extends AbstractTempleFinder { 26 | 27 | public SwampHutFinder(World world, ChunkPos chunkPos) { 28 | super(world, chunkPos, new Vec3i(7, 7, 9)); 29 | } 30 | 31 | public static List create(World world, ChunkPos chunkPos) { 32 | List finders = new ArrayList<>(); 33 | finders.add(new SwampHutFinder(world, chunkPos)); 34 | return finders; 35 | } 36 | 37 | @Override 38 | public List findInChunk() { 39 | Map> result = super.findInChunkPieces(); 40 | List combinedResult = new ArrayList<>(); 41 | 42 | result.forEach((pieceFinder, positions) -> { 43 | combinedResult.addAll(positions); 44 | 45 | positions.forEach(pos -> { 46 | RegionStructure.Data data = Features.SWAMP_HUT.at(this.chunkPos.x, this.chunkPos.z); 47 | 48 | if (SeedCracker.get().getDataStorage().addBaseData(data, DataAddedEvent.POKE_LIFTING)) { 49 | this.addRenderers(pieceFinder, pos, new Color(255, 0, 255)); 50 | } 51 | }); 52 | }); 53 | 54 | return combinedResult; 55 | } 56 | 57 | @Override 58 | protected boolean isValidBiome(Biome biome) { 59 | return Features.SWAMP_HUT.isValidBiome(BiomeFixer.swap(biome)); 60 | } 61 | 62 | @Override 63 | public void buildStructure(PieceFinder finder) { 64 | finder.fillWithOutline(1, 1, 1, 5, 1, 7, Blocks.SPRUCE_PLANKS.getDefaultState(), Blocks.SPRUCE_PLANKS.getDefaultState(), false); 65 | finder.fillWithOutline(1, 4, 2, 5, 4, 7, Blocks.SPRUCE_PLANKS.getDefaultState(), Blocks.SPRUCE_PLANKS.getDefaultState(), false); 66 | finder.fillWithOutline(2, 1, 0, 4, 1, 0, Blocks.SPRUCE_PLANKS.getDefaultState(), Blocks.SPRUCE_PLANKS.getDefaultState(), false); 67 | finder.fillWithOutline(2, 2, 2, 3, 3, 2, Blocks.SPRUCE_PLANKS.getDefaultState(), Blocks.SPRUCE_PLANKS.getDefaultState(), false); 68 | finder.fillWithOutline(1, 2, 3, 1, 3, 6, Blocks.SPRUCE_PLANKS.getDefaultState(), Blocks.SPRUCE_PLANKS.getDefaultState(), false); 69 | finder.fillWithOutline(5, 2, 3, 5, 3, 6, Blocks.SPRUCE_PLANKS.getDefaultState(), Blocks.SPRUCE_PLANKS.getDefaultState(), false); 70 | finder.fillWithOutline(2, 2, 7, 4, 3, 7, Blocks.SPRUCE_PLANKS.getDefaultState(), Blocks.SPRUCE_PLANKS.getDefaultState(), false); 71 | finder.fillWithOutline(1, 0, 2, 1, 3, 2, Blocks.OAK_LOG.getDefaultState(), Blocks.OAK_LOG.getDefaultState(), false); 72 | finder.fillWithOutline(5, 0, 2, 5, 3, 2, Blocks.OAK_LOG.getDefaultState(), Blocks.OAK_LOG.getDefaultState(), false); 73 | finder.fillWithOutline(1, 0, 7, 1, 3, 7, Blocks.OAK_LOG.getDefaultState(), Blocks.OAK_LOG.getDefaultState(), false); 74 | finder.fillWithOutline(5, 0, 7, 5, 3, 7, Blocks.OAK_LOG.getDefaultState(), Blocks.OAK_LOG.getDefaultState(), false); 75 | finder.addBlock(Blocks.OAK_FENCE.getDefaultState(), 2, 3, 2); 76 | finder.addBlock(Blocks.OAK_FENCE.getDefaultState(), 3, 3, 7); 77 | finder.addBlock(Blocks.AIR.getDefaultState(), 1, 3, 4); 78 | finder.addBlock(Blocks.AIR.getDefaultState(), 5, 3, 4); 79 | finder.addBlock(Blocks.AIR.getDefaultState(), 5, 3, 5); 80 | finder.addBlock(Blocks.POTTED_RED_MUSHROOM.getDefaultState(), 1, 3, 5); 81 | finder.addBlock(Blocks.CRAFTING_TABLE.getDefaultState(), 3, 2, 6); 82 | finder.addBlock(Blocks.CAULDRON.getDefaultState(), 4, 2, 6); 83 | finder.addBlock(Blocks.OAK_FENCE.getDefaultState(), 1, 2, 1); 84 | finder.addBlock(Blocks.OAK_FENCE.getDefaultState(), 5, 2, 1); 85 | BlockState northStairs = Blocks.SPRUCE_STAIRS.getDefaultState().with(StairsBlock.FACING, Direction.NORTH); 86 | BlockState eastStairs = Blocks.SPRUCE_STAIRS.getDefaultState().with(StairsBlock.FACING, Direction.EAST); 87 | BlockState westStairs = Blocks.SPRUCE_STAIRS.getDefaultState().with(StairsBlock.FACING, Direction.WEST); 88 | BlockState southStairs = Blocks.SPRUCE_STAIRS.getDefaultState().with(StairsBlock.FACING, Direction.SOUTH); 89 | finder.fillWithOutline(0, 4, 1, 6, 4, 1, northStairs, northStairs, false); 90 | finder.fillWithOutline(0, 4, 2, 0, 4, 7, eastStairs, eastStairs, false); 91 | finder.fillWithOutline(6, 4, 2, 6, 4, 7, westStairs, westStairs, false); 92 | finder.fillWithOutline(0, 4, 8, 6, 4, 8, southStairs, southStairs, false); 93 | finder.addBlock(northStairs.with(StairsBlock.SHAPE, StairShape.OUTER_RIGHT), 0, 4, 1); 94 | finder.addBlock(northStairs.with(StairsBlock.SHAPE, StairShape.OUTER_LEFT), 6, 4, 1); 95 | finder.addBlock(southStairs.with(StairsBlock.SHAPE, StairShape.OUTER_LEFT), 0, 4, 8); 96 | finder.addBlock(southStairs.with(StairsBlock.SHAPE, StairShape.OUTER_RIGHT), 6, 4, 8); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/init/ClientCommands.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.init; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import kaptainwutax.seedcrackerX.command.*; 5 | import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class ClientCommands { 11 | 12 | public static final String PREFIX = "seedcracker"; 13 | public static final List COMMANDS = new ArrayList<>(); 14 | 15 | public static RenderCommand RENDER; 16 | public static FinderCommand FINDER; 17 | public static DataCommand DATA; 18 | public static CrackerCommand CRACKER; 19 | public static VersionCommand VERSION; 20 | public static GuiCommand GUI; 21 | public static DatabaseCommand DATABASE; 22 | 23 | static { 24 | COMMANDS.add(RENDER = new RenderCommand()); 25 | COMMANDS.add(FINDER = new FinderCommand()); 26 | COMMANDS.add(DATA = new DataCommand()); 27 | COMMANDS.add(CRACKER = new CrackerCommand()); 28 | COMMANDS.add(VERSION = new VersionCommand()); 29 | COMMANDS.add(GUI = new GuiCommand()); 30 | COMMANDS.add(DATABASE = new DatabaseCommand()); 31 | } 32 | 33 | public static void registerCommands(CommandDispatcher dispatcher) { 34 | COMMANDS.forEach(clientCommand -> clientCommand.register(dispatcher)); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/mixin/ClientPlayNetworkHandlerMixin.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.mixin; 2 | 3 | import kaptainwutax.seedcrackerX.SeedCracker; 4 | import kaptainwutax.seedcrackerX.config.Config; 5 | import kaptainwutax.seedcrackerX.config.StructureSave; 6 | import kaptainwutax.seedcrackerX.cracker.DataAddedEvent; 7 | import kaptainwutax.seedcrackerX.cracker.HashedSeedData; 8 | import kaptainwutax.seedcrackerX.finder.FinderQueue; 9 | import kaptainwutax.seedcrackerX.finder.ReloadFinders; 10 | import kaptainwutax.seedcrackerX.util.Database; 11 | import kaptainwutax.seedcrackerX.util.Log; 12 | import net.minecraft.client.MinecraftClient; 13 | import net.minecraft.client.network.ClientPlayNetworkHandler; 14 | import net.minecraft.client.world.ClientWorld; 15 | import net.minecraft.network.ClientConnection; 16 | import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket; 17 | import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket; 18 | import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket; 19 | import net.minecraft.util.math.ChunkPos; 20 | import net.minecraft.world.dimension.DimensionType; 21 | import org.spongepowered.asm.mixin.Mixin; 22 | import org.spongepowered.asm.mixin.Shadow; 23 | import org.spongepowered.asm.mixin.Unique; 24 | import org.spongepowered.asm.mixin.injection.At; 25 | import org.spongepowered.asm.mixin.injection.Inject; 26 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 27 | 28 | @Mixin(ClientPlayNetworkHandler.class) 29 | public abstract class ClientPlayNetworkHandlerMixin { 30 | 31 | @Shadow 32 | private ClientWorld world; 33 | 34 | @Shadow public abstract ClientConnection getConnection(); 35 | 36 | @Inject(method = "onChunkData", at = @At(value = "TAIL")) 37 | private void onChunkData(ChunkDataS2CPacket packet, CallbackInfo ci) { 38 | int chunkX = packet.getChunkX(); 39 | int chunkZ = packet.getChunkZ(); 40 | FinderQueue.get().onChunkData(this.world, new ChunkPos(chunkX, chunkZ)); 41 | } 42 | 43 | @Inject(method = "onGameJoin", at = @At(value = "TAIL")) 44 | public void onGameJoin(GameJoinS2CPacket packet, CallbackInfo ci) { 45 | newDimension(new HashedSeedData(packet.commonPlayerSpawnInfo().seed()), false); 46 | tryDatabase(); 47 | var preloaded = StructureSave.loadStructures(); 48 | if (!preloaded.isEmpty()) { 49 | Log.warn("foundRestorableStructures", preloaded.size()); 50 | } 51 | } 52 | 53 | @Inject(method = "onPlayerRespawn", at = @At(value = "TAIL")) 54 | public void onPlayerRespawn(PlayerRespawnS2CPacket packet, CallbackInfo ci) { 55 | newDimension(new HashedSeedData(packet.commonPlayerSpawnInfo().seed()), true); 56 | tryDatabase(); 57 | } 58 | 59 | @Unique 60 | private void newDimension(HashedSeedData hashedSeedData, boolean dimensionChange) { 61 | DimensionType dimension = MinecraftClient.getInstance().world.getDimension(); 62 | ReloadFinders.reloadHeight(dimension.minY(), dimension.minY() + dimension.logicalHeight()); 63 | 64 | if (SeedCracker.get().getDataStorage().addHashedSeedData(hashedSeedData, DataAddedEvent.POKE_BIOMES) && Config.get().active && dimensionChange) { 65 | Log.error(Log.translate("fetchedHashedSeed")); 66 | if (Config.get().debug) { 67 | Log.error("Hashed seed [" + hashedSeedData.getHashedSeed() + "]"); 68 | } 69 | } 70 | } 71 | 72 | @Unique 73 | private void tryDatabase() { 74 | Long seed = Database.getSeed(this.getConnection().getAddress().toString(), SeedCracker.get().getDataStorage().hashedSeedData.getHashedSeed()); 75 | if (seed == null) { 76 | return; 77 | } 78 | Log.printSeed("tmachine.foundWorldSeedFromDatabase", seed); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/mixin/ClientPlayerEntityMixin.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.mixin; 2 | 3 | import kaptainwutax.seedcrackerX.SeedCracker; 4 | import net.minecraft.client.network.ClientPlayerEntity; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 9 | 10 | @Mixin(ClientPlayerEntity.class) 11 | public abstract class ClientPlayerEntityMixin { 12 | 13 | @Inject(method = "tick", at = @At("HEAD")) 14 | private void tick(CallbackInfo ci) { 15 | SeedCracker.get().getDataStorage().tick(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/mixin/ClientWorldMixin.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.mixin; 2 | 3 | import kaptainwutax.seedcrackerX.SeedCracker; 4 | import kaptainwutax.seedcrackerX.config.StructureSave; 5 | import net.minecraft.client.world.ClientWorld; 6 | import net.minecraft.registry.DynamicRegistryManager; 7 | import net.minecraft.registry.RegistryKey; 8 | import net.minecraft.registry.RegistryKeys; 9 | import net.minecraft.registry.entry.RegistryEntry; 10 | import net.minecraft.world.MutableWorldProperties; 11 | import net.minecraft.world.World; 12 | import net.minecraft.world.biome.Biome; 13 | import net.minecraft.world.biome.BiomeKeys; 14 | import net.minecraft.world.dimension.DimensionType; 15 | import org.spongepowered.asm.mixin.Mixin; 16 | import org.spongepowered.asm.mixin.injection.At; 17 | import org.spongepowered.asm.mixin.injection.Inject; 18 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 19 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 20 | 21 | @Mixin(ClientWorld.class) 22 | public abstract class ClientWorldMixin extends World { 23 | 24 | protected ClientWorldMixin(MutableWorldProperties properties, RegistryKey registryRef, DynamicRegistryManager registryManager, RegistryEntry dimensionEntry, boolean isClient, boolean debugWorld, long biomeAccess, int maxChainedNeighborUpdates) { 25 | super(properties, registryRef, registryManager, dimensionEntry, isClient, debugWorld, biomeAccess, maxChainedNeighborUpdates); 26 | } 27 | 28 | @Inject(method = "disconnect", at = @At("HEAD")) 29 | private void disconnect(CallbackInfo ci) { 30 | StructureSave.saveStructures(SeedCracker.get().getDataStorage().baseSeedData); 31 | SeedCracker.get().reset(); 32 | } 33 | 34 | @Inject(method = "getGeneratorStoredBiome", at = @At("HEAD"), cancellable = true) 35 | private void getGeneratorStoredBiome(int x, int y, int z, CallbackInfoReturnable> ci) { 36 | var biome = getRegistryManager().getOrThrow(RegistryKeys.BIOME).getOptional(BiomeKeys.THE_VOID); 37 | biome.ifPresent(ci::setReturnValue); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/render/Color.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.render; 2 | 3 | public record Color(int red, int green, int blue) { 4 | 5 | public static final Color WHITE = new Color(255, 255, 255); 6 | 7 | public float getFRed() { 8 | return this.red() / 255.0F; 9 | } 10 | 11 | public float getFGreen() { 12 | return this.green() / 255.0F; 13 | } 14 | 15 | public float getFBlue() { 16 | return this.blue() / 255.0F; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/render/Cube.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.render; 2 | 3 | import net.minecraft.util.math.BlockPos; 4 | import net.minecraft.util.math.Vec3i; 5 | 6 | public class Cube extends Cuboid { 7 | 8 | public Cube() { 9 | this(BlockPos.ORIGIN, Color.WHITE); 10 | } 11 | 12 | public Cube(BlockPos pos) { 13 | this(pos, Color.WHITE); 14 | } 15 | 16 | public Cube(BlockPos pos, Color color) { 17 | super(pos, new Vec3i(1, 1, 1), color); 18 | } 19 | 20 | @Override 21 | public BlockPos getPos() { 22 | return this.start; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/render/Cuboid.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.render; 2 | 3 | import net.minecraft.client.render.VertexConsumer; 4 | import net.minecraft.client.util.math.MatrixStack; 5 | import net.minecraft.util.math.BlockBox; 6 | import net.minecraft.util.math.BlockPos; 7 | import net.minecraft.util.math.Vec3d; 8 | import net.minecraft.util.math.Vec3i; 9 | 10 | public class Cuboid extends Renderer { 11 | 12 | private final Line[] edges = new Line[12]; 13 | public BlockPos start; 14 | public Vec3i size; 15 | public BlockPos pos; 16 | 17 | public Cuboid() { 18 | this(BlockPos.ORIGIN, BlockPos.ORIGIN, Color.WHITE); 19 | } 20 | 21 | public Cuboid(BlockPos pos) { 22 | this(pos, new BlockPos(1, 1, 1), Color.WHITE); 23 | } 24 | 25 | public Cuboid(BlockPos start, BlockPos end, Color color) { 26 | this(start, new Vec3i(end.getX() - start.getX(), end.getY() - start.getY(), end.getZ() - start.getZ()), color); 27 | } 28 | 29 | public Cuboid(BlockBox box, Color color) { 30 | this(new BlockPos(box.getMinX(), box.getMinY(), box.getMinZ()), new BlockPos(box.getMaxX(), box.getMaxY(), box.getMaxZ()), color); 31 | } 32 | 33 | public Cuboid(BlockPos start, Vec3i size, Color color) { 34 | this.start = start; 35 | this.size = size; 36 | this.pos = this.start.add(this.size.getX() / 2, this.size.getY() / 2, this.size.getZ() / 2); 37 | this.edges[0] = new Line(toVec3d(this.start), toVec3d(this.start.add(this.size.getX(), 0, 0)), color); 38 | this.edges[1] = new Line(toVec3d(this.start), toVec3d(this.start.add(0, this.size.getY(), 0)), color); 39 | this.edges[2] = new Line(toVec3d(this.start), toVec3d(this.start.add(0, 0, this.size.getZ())), color); 40 | this.edges[3] = new Line(toVec3d(this.start.add(this.size.getX(), 0, this.size.getZ())), toVec3d(this.start.add(this.size.getX(), 0, 0)), color); 41 | this.edges[4] = new Line(toVec3d(this.start.add(this.size.getX(), 0, this.size.getZ())), toVec3d(this.start.add(this.size.getX(), this.size.getY(), this.size.getZ())), color); 42 | this.edges[5] = new Line(toVec3d(this.start.add(this.size.getX(), 0, this.size.getZ())), toVec3d(this.start.add(0, 0, this.size.getZ())), color); 43 | this.edges[6] = new Line(toVec3d(this.start.add(this.size.getX(), this.size.getY(), 0)), toVec3d(this.start.add(this.size.getX(), 0, 0)), color); 44 | this.edges[7] = new Line(toVec3d(this.start.add(this.size.getX(), this.size.getY(), 0)), toVec3d(this.start.add(0, this.size.getY(), 0)), color); 45 | this.edges[8] = new Line(toVec3d(this.start.add(this.size.getX(), this.size.getY(), 0)), toVec3d(this.start.add(this.size.getX(), this.size.getY(), this.size.getZ())), color); 46 | this.edges[9] = new Line(toVec3d(this.start.add(0, this.size.getY(), this.size.getZ())), toVec3d(this.start.add(0, 0, this.size.getZ())), color); 47 | this.edges[10] = new Line(toVec3d(this.start.add(0, this.size.getY(), this.size.getZ())), toVec3d(this.start.add(0, this.size.getY(), 0)), color); 48 | this.edges[11] = new Line(toVec3d(this.start.add(0, this.size.getY(), this.size.getZ())), toVec3d(this.start.add(this.size.getX(), this.size.getY(), this.size.getZ())), color); 49 | } 50 | 51 | @Override 52 | public void render(MatrixStack.Entry matrix4f, VertexConsumer vertexConsumer, Vec3d cameraPos) { 53 | if (this.start == null || this.size == null || this.edges == null) return; 54 | 55 | for (Line edge : this.edges) { 56 | if (edge == null) continue; 57 | edge.render(matrix4f, vertexConsumer, cameraPos); 58 | } 59 | } 60 | 61 | @Override 62 | public BlockPos getPos() { 63 | return pos; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/render/Line.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.render; 2 | 3 | import net.minecraft.client.render.VertexConsumer; 4 | import net.minecraft.client.util.math.MatrixStack; 5 | import net.minecraft.util.math.BlockPos; 6 | import net.minecraft.util.math.Vec3d; 7 | 8 | public class Line extends Renderer { 9 | 10 | public Vec3d start; 11 | public Vec3d end; 12 | public Color color; 13 | 14 | public Line() { 15 | this(Vec3d.ZERO, Vec3d.ZERO, Color.WHITE); 16 | } 17 | 18 | public Line(Vec3d start, Vec3d end) { 19 | this(start, end, Color.WHITE); 20 | } 21 | 22 | public Line(Vec3d start, Vec3d end, Color color) { 23 | this.start = start; 24 | this.end = end; 25 | this.color = color; 26 | } 27 | 28 | @Override 29 | public void render(MatrixStack.Entry matrix4f, VertexConsumer vertexConsumer, Vec3d cameraPos) { 30 | Vec3d normal = this.end.subtract(this.start).normalize(); 31 | this.putVertex(vertexConsumer, matrix4f, this.start,normal, cameraPos); 32 | this.putVertex(vertexConsumer, matrix4f, this.end, normal, cameraPos); 33 | } 34 | 35 | protected void putVertex(VertexConsumer vertexConsumer, MatrixStack.Entry matrix4f, Vec3d pos, Vec3d normal, Vec3d cameraPos) { 36 | vertexConsumer.vertex( 37 | matrix4f, 38 | (float) (pos.x - cameraPos.x), 39 | (float) (pos.y - cameraPos.y), 40 | (float) (pos.z - cameraPos.z) 41 | ).color( 42 | this.color.getFRed(), 43 | this.color.getFGreen(), 44 | this.color.getFBlue(), 45 | 1.0F 46 | ).normal( 47 | matrix4f, 48 | (float) normal.getX(), 49 | (float) normal.getY(), 50 | (float) normal.getZ() 51 | ); 52 | } 53 | 54 | @Override 55 | public BlockPos getPos() { 56 | double x = (this.end.getX() - this.start.getX()) / 2 + this.start.getX(); 57 | double y = (this.end.getY() - this.start.getY()) / 2 + this.start.getY(); 58 | double z = (this.end.getZ() - this.start.getZ()) / 2 + this.start.getZ(); 59 | return BlockPos.ofFloored(x, y, z); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/render/Renderer.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.render; 2 | 3 | import net.minecraft.client.render.VertexConsumer; 4 | import net.minecraft.client.util.math.MatrixStack; 5 | import net.minecraft.util.math.BlockPos; 6 | import net.minecraft.util.math.Vec3d; 7 | 8 | public abstract class Renderer { 9 | 10 | public abstract void render(MatrixStack.Entry matrix, VertexConsumer vertexConsumer, Vec3d cameraPos); 11 | 12 | public abstract BlockPos getPos(); 13 | 14 | protected Vec3d toVec3d(BlockPos pos) { 15 | return new Vec3d(pos.getX(), pos.getY(), pos.getZ()); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/util/BiomeFixer.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.util; 2 | 3 | import com.seedfinding.mcbiome.biome.Biome; 4 | import com.seedfinding.mcbiome.biome.Biomes; 5 | import net.minecraft.client.MinecraftClient; 6 | import net.minecraft.client.network.ClientPlayNetworkHandler; 7 | import net.minecraft.registry.BuiltinRegistries; 8 | import net.minecraft.registry.RegistryKey; 9 | import net.minecraft.registry.RegistryKeys; 10 | import net.minecraft.util.Identifier; 11 | import net.minecraft.world.biome.BiomeKeys; 12 | 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | 16 | public class BiomeFixer { 17 | 18 | private static final Map COMPATREGISTRY = new HashMap<>(); 19 | 20 | static { 21 | for (Biome biome : Biomes.REGISTRY.values()) { 22 | COMPATREGISTRY.put(biome.getName(), biome); 23 | } 24 | //renamed 25 | COMPATREGISTRY.put("snowy_plains", Biomes.SNOWY_TUNDRA); 26 | COMPATREGISTRY.put("old_growth_birch_forest", Biomes.TALL_BIRCH_FOREST); 27 | COMPATREGISTRY.put("old_growth_pine_taiga", Biomes.GIANT_TREE_TAIGA); 28 | COMPATREGISTRY.put("old_growth_spruce_taiga", Biomes.GIANT_TREE_TAIGA); 29 | COMPATREGISTRY.put("windswept_hills", Biomes.EXTREME_HILLS); 30 | COMPATREGISTRY.put("windswept_forest", Biomes.WOODED_MOUNTAINS); 31 | COMPATREGISTRY.put("windswept_gravelly_hills", Biomes.GRAVELLY_MOUNTAINS); 32 | COMPATREGISTRY.put("windswept_savanna", Biomes.SHATTERED_SAVANNA); 33 | COMPATREGISTRY.put("sparse_jungle", Biomes.JUNGLE_EDGE); 34 | COMPATREGISTRY.put("stony_shore", Biomes.STONE_SHORE); 35 | //new 36 | COMPATREGISTRY.put("meadow", Biomes.PLAINS); 37 | COMPATREGISTRY.put("grove", Biomes.TAIGA); 38 | COMPATREGISTRY.put("snowy_slopes", Biomes.SNOWY_TUNDRA); 39 | COMPATREGISTRY.put("frozen_peaks", Biomes.TAIGA); 40 | COMPATREGISTRY.put("jagged_peaks", Biomes.TAIGA); 41 | COMPATREGISTRY.put("stony_peaks", Biomes.TAIGA); 42 | COMPATREGISTRY.put("mangrove_swamp", Biomes.SWAMP); 43 | 44 | //unsure what to do with those, they'll return THE_VOID for now 45 | //dripstone_caves 46 | //lush_caves 47 | //deep_dark 48 | } 49 | 50 | public static Biome swap(net.minecraft.world.biome.Biome biome) { 51 | ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); 52 | if (networkHandler == null) return Biomes.VOID; 53 | 54 | Identifier biomeID = networkHandler 55 | .getRegistryManager() 56 | .getOptional(RegistryKeys.BIOME) 57 | .map(reg -> reg.getId(biome)) 58 | .orElse(null); 59 | 60 | if (biomeID == null) return Biomes.THE_VOID; 61 | 62 | return COMPATREGISTRY.getOrDefault(biomeID.getPath(), Biomes.VOID); 63 | } 64 | 65 | public static net.minecraft.world.biome.Biome swap(Biome biome) { 66 | // internal, meh 67 | var biomeRegistries = BuiltinRegistries.createWrapperLookup().getOrThrow(RegistryKeys.BIOME); 68 | 69 | return biomeRegistries.getOptional(RegistryKey.of(RegistryKeys.BIOME, Identifier.ofVanilla(biome.getName()))).orElse( 70 | biomeRegistries.getOrThrow(BiomeKeys.THE_VOID) 71 | ).value(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/util/Database.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.util; 2 | 3 | import com.mojang.authlib.HttpAuthenticationService; 4 | import com.mojang.authlib.exceptions.AuthenticationException; 5 | import com.mojang.authlib.exceptions.AuthenticationUnavailableException; 6 | import com.mojang.authlib.exceptions.InsufficientPrivilegesException; 7 | import com.mojang.authlib.exceptions.InvalidCredentialsException; 8 | import kaptainwutax.seedcrackerX.config.Config; 9 | import net.minecraft.client.MinecraftClient; 10 | import net.minecraft.text.Text; 11 | import org.apache.http.HttpHeaders; 12 | import org.apache.http.HttpStatus; 13 | import org.apache.http.entity.ContentType; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | import java.io.IOException; 17 | import java.net.URI; 18 | import java.net.http.HttpClient; 19 | import java.net.http.HttpRequest; 20 | import java.net.http.HttpResponse; 21 | import java.time.Duration; 22 | import java.util.Arrays; 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | public class Database { 27 | 28 | private static final String DATABASE_POST_URL = "https://script.google.com/macros/s/AKfycbye87L-fEYq2EkgczvhKb_kGecp5wL1oX95vg45TRSwNvpv7K-53zoInGTeI1FZ0kv7DA/exec"; 29 | private static final String DATABASE_URL = "https://docs.google.com/spreadsheets/d/1tuQiE-0leW88em9OHbZnH-RFNhVqgoHhIt9WQbeqqWw/export?format=csv&gid=0"; // script link is not updated, this works fine 30 | private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build(); 31 | private static final Duration TIMEOUT = Duration.ofSeconds(10); 32 | private static final String SEEDCRACKERX_USER_AGENT = "SeedcrackerX mod"; 33 | 34 | private static final Map connectionToSeed = new HashMap<>(); 35 | private static final Map hashedSeedToSeed = new HashMap<>(); 36 | 37 | public static Text joinFakeServerForAuth() { 38 | try { 39 | MinecraftClient client = MinecraftClient.getInstance(); 40 | client.getSessionService().joinServer(client.getSession().getUuidOrNull(), client.getSession().getAccessToken(), "seedcrackerx"); 41 | } 42 | catch (AuthenticationUnavailableException authenticationUnavailableException) { 43 | return Text.translatable("disconnect.loginFailedInfo", Text.translatable("disconnect.loginFailedInfo.serversUnavailable")); 44 | } 45 | catch (InvalidCredentialsException authenticationUnavailableException) { 46 | return Text.translatable("disconnect.loginFailedInfo", Text.translatable("disconnect.loginFailedInfo.invalidSession")); 47 | } 48 | catch (InsufficientPrivilegesException authenticationUnavailableException) { 49 | return Text.translatable("disconnect.loginFailedInfo", Text.translatable("disconnect.loginFailedInfo.insufficientPrivileges")); 50 | } 51 | catch (AuthenticationException authenticationUnavailableException) { 52 | return Text.translatable("disconnect.loginFailedInfo", authenticationUnavailableException.getMessage()); 53 | } 54 | return null; 55 | } 56 | 57 | public static @Nullable Long getSeed(String connection, long hashedSeed) { 58 | Long seed = connectionToSeed.get(connection); 59 | if (seed != null) { 60 | return seed; 61 | } 62 | return hashedSeedToSeed.get(hashedSeed); 63 | } 64 | 65 | public static void handleDatabaseCall(Long seed) { 66 | MinecraftClient client = MinecraftClient.getInstance(); 67 | Map data = new HashMap<>(); 68 | data.put("serverIp", client.getNetworkHandler().getConnection().getAddress().toString()); 69 | data.put("dimension", client.world.getDimension().effects().getPath()); 70 | data.put("seed", seed+"L"); //javascript backend likes floating point. so we need to convert it to a string 71 | data.put("version", Config.get().getVersion().name); 72 | data.put("username", client.player.getName().getString()); 73 | data.put("hash", Config.get().anonymusSubmits? 1 : 0); 74 | 75 | HttpRequest request = HttpRequest.newBuilder(URI.create(DATABASE_POST_URL)) 76 | .timeout(TIMEOUT) 77 | .POST(HttpRequest.BodyPublishers.ofString(HttpAuthenticationService.buildQuery(data))) 78 | .setHeader(HttpHeaders.USER_AGENT, SEEDCRACKERX_USER_AGENT) 79 | .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.getMimeType()) 80 | .build(); 81 | 82 | try { 83 | HttpResponse response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString()); 84 | if (response.statusCode() == HttpStatus.SC_MOVED_TEMPORARILY) { //the page says "document moved" but the post gets processed 85 | Log.warn("database.success"); 86 | } else { 87 | Log.warn("database.fail"); 88 | } 89 | } catch (IOException | InterruptedException e) { 90 | Log.warn("database.fail"); 91 | } 92 | } 93 | 94 | public static void fetchSeeds() { 95 | HttpRequest request = HttpRequest.newBuilder(URI.create(DATABASE_URL)) 96 | .timeout(TIMEOUT) 97 | .GET() 98 | .setHeader(HttpHeaders.USER_AGENT, SEEDCRACKERX_USER_AGENT) 99 | .build(); 100 | HTTP_CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString()) 101 | .thenApply(HttpResponse::body) 102 | .thenAccept(Database::parseCsv); 103 | } 104 | 105 | private static void parseCsv(String csv) { 106 | Arrays.stream(csv.split("\n")).skip(1).forEach(row -> { 107 | try { 108 | String[] seedEntry = row.split(","); 109 | String connection = seedEntry[0]; 110 | String seedString = seedEntry[2]; 111 | long seed = Long.parseLong(seedString.substring(0, seedString.length() - 1)); 112 | connectionToSeed.put(connection, seed); 113 | long hashedSeed = Long.parseLong(seedEntry[6]); 114 | hashedSeedToSeed.put(hashedSeed, seed); 115 | } catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) { 116 | } 117 | }); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/util/FeatureToggle.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.util; 2 | 3 | public class FeatureToggle { 4 | 5 | //This is for The featureToggles in the config object 6 | //It allows for the booleans to be passed around by reference 7 | //(I know that it's a hacky workaround) 8 | private boolean enabled; 9 | 10 | public FeatureToggle(boolean flag) { 11 | enabled = flag; 12 | } 13 | 14 | public void set(boolean flag) { 15 | enabled = flag; 16 | } 17 | 18 | public boolean get() { 19 | return enabled; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/util/HeightContext.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.util; 2 | 3 | public class HeightContext { 4 | private final int bottomY; 5 | private final int topY; 6 | 7 | public HeightContext(int minY, int maxY) { 8 | this.bottomY = minY; 9 | this.topY = maxY; 10 | } 11 | 12 | public int getTopY() { 13 | return topY; 14 | } 15 | 16 | public int getBottomY() { 17 | return bottomY; 18 | } 19 | 20 | public int getHeight() { 21 | return topY - bottomY; 22 | } 23 | 24 | public int getDistanceToBottom(int yValue) { 25 | return yValue - bottomY; 26 | } 27 | 28 | public int getDistanceToTop(int yValue) { 29 | return topY - yValue - 1; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/util/Log.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.util; 2 | 3 | import net.minecraft.client.MinecraftClient; 4 | import net.minecraft.entity.player.PlayerEntity; 5 | import net.minecraft.text.*; 6 | import net.minecraft.util.Formatting; 7 | import net.minecraft.util.Language; 8 | 9 | import java.util.regex.Pattern; 10 | 11 | public class Log { 12 | 13 | public static void debug(String message) { 14 | PlayerEntity player = getPlayer(); 15 | 16 | if (player != null) { 17 | schedule(() -> player.sendMessage(Text.literal(message), false)); 18 | } 19 | } 20 | 21 | public static void warn(String translateKey, Object... args) { 22 | String message = translate(translateKey).formatted(args); 23 | PlayerEntity player = getPlayer(); 24 | 25 | if (player != null) { 26 | schedule(() -> player.sendMessage(Text.literal(message).formatted(Formatting.GREEN), false)); 27 | } 28 | } 29 | 30 | public static void warn(String translateKey) { 31 | warn(translateKey, new Object[]{}); 32 | } 33 | 34 | public static void error(String translateKey) { 35 | String message = translate(translateKey); 36 | PlayerEntity player = getPlayer(); 37 | 38 | if (player != null) { 39 | schedule(() -> player.sendMessage(Text.literal(message).formatted(Formatting.RED), false)); 40 | } 41 | } 42 | 43 | public static void printSeed(String translateKey, long seedValue) { 44 | String message = translate(translateKey); 45 | String[] data = message.split(Pattern.quote("${SEED}")); 46 | String seed = String.valueOf(seedValue); 47 | Text text = Texts.bracketed((Text.literal(seed)).styled(style -> style.withColor(Formatting.GREEN).withClickEvent(new ClickEvent.CopyToClipboard(seed)).withHoverEvent(new HoverEvent.ShowText(Text.translatable("chat.copy.click"))).withInsertion(seed))); 48 | 49 | PlayerEntity player = getPlayer(); 50 | 51 | if (player != null) { 52 | MutableText text1 = Text.literal(data[0]).append(text); 53 | if (data.length > 1) { 54 | text1.append(Text.literal(data[1])); 55 | } 56 | schedule(() -> player.sendMessage(text1, false)); 57 | } 58 | } 59 | 60 | public static void printDungeonInfo(String message) { 61 | Text text = Texts.bracketed((Text.literal(message)).styled(style -> style.withColor(Formatting.GREEN).withClickEvent(new ClickEvent.CopyToClipboard(message)).withHoverEvent(new HoverEvent.ShowText( Text.translatable("chat.copy.click"))).withInsertion(message))); 62 | 63 | PlayerEntity player = getPlayer(); 64 | 65 | if (player != null) { 66 | schedule(() -> player.sendMessage(text, false)); 67 | } 68 | } 69 | 70 | public static String translate(String translateKey) { 71 | return Language.getInstance().get(translateKey); 72 | } 73 | 74 | private static void schedule(Runnable runnable) { 75 | MinecraftClient.getInstance().execute(runnable); 76 | } 77 | 78 | private static PlayerEntity getPlayer() { 79 | return MinecraftClient.getInstance().player; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/util/PosIterator.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.util; 2 | 3 | import net.minecraft.util.math.BlockPos; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | public class PosIterator { 9 | 10 | public static Set create(BlockPos start, BlockPos end) { 11 | Set result = new HashSet<>(); 12 | 13 | for (int x = start.getX(); x <= end.getX(); x++) { 14 | for (int z = start.getZ(); z <= end.getZ(); z++) { 15 | for (int y = start.getY(); y <= end.getY(); y++) { 16 | result.add(new BlockPos(x, y, z)); 17 | } 18 | } 19 | } 20 | 21 | return result; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/kaptainwutax/seedcrackerX/util/Predicates.java: -------------------------------------------------------------------------------- 1 | package kaptainwutax.seedcrackerX.util; 2 | 3 | import java.util.function.BiPredicate; 4 | 5 | public class Predicates { 6 | 7 | public static BiPredicate EQUAL_TO = Integer::equals; 8 | public static BiPredicate NOT_EQUAL_TO = (a, b) -> !a.equals(b); 9 | public static BiPredicate LESS_THAN = (a, b) -> a < b; 10 | public static BiPredicate MORE_THAN = (a, b) -> a > b; 11 | public static BiPredicate LESS_OR_EQUAL_TO = (a, b) -> a <= b; 12 | public static BiPredicate MORE_OR_EQUAL_TO = (a, b) -> a >= b; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/assets/seedcrackerx/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/19MisterX98/SeedcrackerX/5b599dc241ea059f8ed2ce7f25414fed9db2b56b/src/main/resources/assets/seedcrackerx/icon.png -------------------------------------------------------------------------------- /src/main/resources/assets/seedcrackerx/lang/en_us.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Seed Cracker X", 3 | "settings": "Settings", 4 | "settings.active": "Active", 5 | "settings.database": "Send 10+ player server seeds to the database", 6 | "settings.hideNameDatabase": "Scramble username in seed database", 7 | "settings.openDatabase": "Open the database", 8 | "settings.version": "Version", 9 | "settings.visuals": "Visuals", 10 | "settings.outline": "Render outlines", 11 | "settings.finderToggles": "Finder toggles", 12 | "settings.antiXrayMode": "Anti Xray Mode", 13 | "settings.antiAntiXrayExplained": "Sends packets to the server if a dungeon floor isn't only out of cobble and mossy cobble. In response the server tells the client the real blocks. This may trigger hyper sensitive anti cheats but nobody complained about bans/kicks yet (version 2.9.0 has this feature always on and has ~2000 downloads currently). It makes the process much smoother and therefore I highly recommend leaving it on", 14 | "finder.buriedTreasures": "Buried treasures", 15 | "finder.desertTemples": "Desert temples", 16 | "finder.endCities": "End cities", 17 | "finder.jungleTemples": "Jungle temples", 18 | "finder.monuments": "Ocean monuments", 19 | "finder.swampHuts": "Witch huts", 20 | "finder.shipwrecks": "Shipwrecks", 21 | "finder.outposts": "Pillager Outposts", 22 | "finder.igloo": "Igloos", 23 | "finder.endPillars": "End pillars", 24 | "finder.endGateways": "End gateways", 25 | "finder.dungeons": "Dungeons", 26 | "finder.emeraldOres": "Emerald ores", 27 | "finder.desertWells": "Desert wells", 28 | "finder.warpedFungus": "Warped fungus", 29 | "finder.biomes": "Biomes", 30 | "finder.isFinder": "Finder %s is set to", 31 | "finder.setFinder": "Finder %s has been set to", 32 | "info": "Info", 33 | "info.clearData": "Clear data", 34 | "info.worldSeeds": "World seeds", 35 | "info.noWorldSeeds": "No world seeds found", 36 | "info.structureSeeds": "Structure seeds", 37 | "info.noStructureSeeds": "No structure seeds found", 38 | "info.pillarSeeds": "Pillar seeds", 39 | "info.noPillarSeeds": "No pillar seeds found", 40 | "info.hashedSeed": "Hashed seed", 41 | "info.noHashedSeed": "No hashed seed found", 42 | "fetchedHashedSeed": "The world seed in this dimension is different", 43 | "foundRestorableStructures": "Found %s structure/s from the previous session. Restore them with /seedcracker data restore", 44 | "foundStructureSeed": "Found structure seed ${SEED}.", 45 | "finishedSearchNoResult": "Finished search with no results.", 46 | "crossCompare": "Cross-compared seeds and reduced to ${SEED}.", 47 | "data.clearData": "Cleared data storage", 48 | "data.collectedBits": "You currently have collected %s bits out of %s.", 49 | "data.collectedLiftingBits": "You currently have collected %s bits from liftable structures out of %s.", 50 | "data.restoreStructures": "Restored %s structure/s", 51 | "data.restoreFailed": "no structures from the previous session found", 52 | "cracker.successfully": "Successfully ", 53 | "cracker.already": "already ", 54 | "cracker.enabled": "enabled", 55 | "cracker.disabled": "disabled", 56 | "render.getRenderMode": "Current render mode is set to", 57 | "render.setRenderMode": "Changed render mode to", 58 | "version.setVersion": "Changed version to", 59 | "tmachine.lookingForPillarSeed": "Looking for pillar seeds...", 60 | "tmachine.foundPillarSeed": "Found pillar seed ${SEED}.", 61 | "tmachine.pillarSeedSearchFinished": "Finished searching for pillar seeds.", 62 | "tmachine.lookingForStructureSeeds": "Looking for structure seeds with pillar seed [%s]...", 63 | "tmachine.progress": "Progress", 64 | "tmachine.structureSeedSearchFinished": "Finished searching for structure seeds.", 65 | "tmachine.decoratorWorldSeedSearch": "Looking for world seeds with decorators...", 66 | "tmachine.hashedSeedWorldSeedSearch": "Looking for world seeds with hashed seed...", 67 | "tmachine.foundWorldSeed": "Found world seed ${SEED}.", 68 | "tmachine.foundWorldSeedFromDatabase": "Found world seed ${SEED} from database.", 69 | "tmachine.worldSeedSearchFinished": "Finished searching for world seeds.", 70 | "tmachine.noResultsRevertingToBiomes": "Finished search with no results, reverting back to biomes.", 71 | "tmachine.moreBiomesNeeded": "You need to collect more biome information", 72 | "tmachine.biomeWorldSeedSearch": "Looking for world seeds with %s biomes...", 73 | "tmachine.fuzzyBiomeSearch": "Trying fuzzy biome search", 74 | "tmachine.deepBiomeSearch": "trying deep biome search", 75 | "tmachine.printSeedsInConsole": "[Spam protection] printing all other seeds in console", 76 | "tmachine.deleteBiomeInformation": "Deleting biome information since no matching seed was found", 77 | "tmachine.randomSeedSearch": "Looking for world seeds that are possible if the world uses a random seed", 78 | "tmachine.startLifting": "Started lifting with %s structures. This takes a few minutes", 79 | "tmachine.reduceSeeds": "Reducing %s structure seeds", 80 | "tmachine.succeedReducing": "Reduced to %s structure seeds", 81 | "tmachine.failedReducing": "Failed to reduce seeds. You probably need more structures or your data is wrong", 82 | "dungeon.start": "Short-cutting to dungeons...", 83 | "dungeon.structureSeedSearchFailed": "Finished dungeon search with no seeds.", 84 | "dungeon.finishedNeedAnotherOne": "finished structure seed search. You'll need another dungeon", 85 | "fungus.start": "running cracker at %s %s", 86 | "fungus.fungusSeed": "fungus seed: ${SEED}.", 87 | "fungus.wrongData": "No Fungus seed, fungus was modified (also includes changes during generation)", 88 | "fungus.noStructureSeedsFound": "no seeds found for this Fungus.", 89 | "fungus.gotStructureSeeds": "got structure seeds:", 90 | "fungus.usableAsWorldSeed": "this structure seed is also usable as worldseed", 91 | "database.success": "sent seed to database successfully", 92 | "database.fail": "failed to send the seed to database" 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/resources/assets/seedcrackerx/lang/hi_in.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Seed Cracker X", 3 | "settings": "सेटिंग्स", 4 | "settings.active": "सक्रिय", 5 | "settings.database": "10 से अधिक प्लेयर्स वाले सर्वेरों के सीड को डेटाबेस में भेजता है", 6 | "settings.hideNameDatabase": "सीड डेटाबेस में उपयोगकर्ता नाम छुपाएं", 7 | "settings.openDatabase": "डेटाबेस खोलें", 8 | "settings.version": "संस्करण", 9 | "settings.visuals": "दृश्य", 10 | "settings.outline": "रूपरेखाएँ दिखाएँ", 11 | "settings.finderToggles": "खोजक टॉगल", 12 | "settings.antiXrayMode": "एक्स-रे विरुद्ध मोड", 13 | "settings.antiAntiXrayExplained": "सर्वर को पैकेट भेजता है अगर डंजियन का फर्श कोब्बल या मॉसी कोब्बल से बना है जवाब में सर्वर क्लाइंट को असली ब्लॉक बता देता है। यह बहुत अधिक संवेदनशील एंटी चीट को उत्प्रेरित कर सकता है लेकिन अब तक किसी ने बैन/किक के बारे में शिकायत नहीं की है (संस्करण 2.9.0 में यह फीचर हमेशा सक्रिय रहता है और वर्तमान में इसके ~2000 डाउनलोड हैं)। यह प्रिक्रिया को अधिक सरल बना देता है इसलिए में इसे सक्रिय रखने कि सलाह देता हूँ", 14 | "finder.buriedTreasures": "दफ़न खजाना", 15 | "finder.desertTemples": "डेजर्ट टेम्पल", 16 | "finder.endCities": "एन्ड सिटी", 17 | "finder.jungleTemples": "जंगल टेम्पल", 18 | "finder.monuments": "ओसियन मोन्यूमेंट", 19 | "finder.swampHuts": "विच है", 20 | "finder.shipwrecks": "शिपरेक", 21 | "finder.outposts": "पिलेजर", 22 | "finder.igloo": "इग्लू", 23 | "finder.endPillars": "एन्ड पिलर", 24 | "finder.endGateways": "एन्ड गेटवे", 25 | "finder.dungeons": "डंजियन", 26 | "finder.emeraldOres": "एमराल्ड अयस्क", 27 | "finder.desertWells": "डेजर्ट कुएँ", 28 | "finder.warpedFungus": "वार्पड फंगस", 29 | "finder.biomes": "बायोम", 30 | "finder.isFinder": "खोजक %s सेट है", 31 | "finder.setFinder": "खोजक %s सेट कर दिया गया है", 32 | "info": "जानकारी", 33 | "info.clearData": "डेटा हटाएँ", 34 | "info.worldSeeds": "वर्ल्ड सीड", 35 | "info.noWorldSeeds": "कोई वर्ल्ड सीड नहीं मिले", 36 | "info.structureSeeds": "सरंचना सीड", 37 | "info.noStructureSeeds": "कोई सरंचना सीड नहीं मिले", 38 | "info.pillarSeeds": "पिलर सीड", 39 | "info.noPillarSeeds": "कोई पिलर सीड नहीं मिले", 40 | "info.hashedSeed": "हैश हुआ सीड", 41 | "info.noHashedSeed": "कोई हैश हुआ सीड नहीं मिला", 42 | "fetchedHashedSeed": "इस आयाम में वर्ल्ड सीड अलग है", 43 | "foundRestorableStructures": "पिछले सत्र से %s सरंचनाएँ मिली। /seedcracker data restore से उन्हें वापिस लाइए", 44 | "foundStructureSeed": "सरंचना सीड मिला ${SEED}.", 45 | "finishedSearchNoResult": "बिना कोई परिणामो के खोज पूरी हुई।", 46 | "crossCompare": "सीड की तुलना की और घटाए गए ${SEED}.", 47 | "data.clearData": "स्टोरेज डेटा हटाया गया", 48 | "data.collectedBits": "आपने वर्तमान में %s बिट संग्रहीत कर लिए हैं %s में से।", 49 | "data.collectedLiftingBits": "आपने वर्तमान में उठाने योग्य सरंचनाओं से %s बिट संग्रहीत कर लिए हैं %s में से।", 50 | "data.restoreStructures": "%s सरंचनाएँ वापिस लायी गयी", 51 | "data.restoreFailed": "पिछले सत्र से कोई सरंचनाएँ नहीं मिली", 52 | "cracker.successfully": "सफलतापूर्वक ", 53 | "cracker.already": "पहले से ही ", 54 | "cracker.enabled": "सक्षम", 55 | "cracker.disabled": "अक्षम", 56 | "render.getRenderMode": "वर्तमान रेंडर मोड सेट है", 57 | "render.setRenderMode": "रेंडर मोड में बदला गया", 58 | "version.setVersion": "संस्करण में बदला गया", 59 | "tmachine.lookingForPillarSeed": "पिलर सीड खोज रहा है...", 60 | "tmachine.foundPillarSeed": "पिलर सीड मिल गया ${SEED}.", 61 | "tmachine.pillarSeedSearchFinished": "पिलर सीड खोज समाप्त हुयी।", 62 | "tmachine.lookingForStructureSeeds": "पिलर सीड [%s] से सरंचना सीड खोज रहा है...", 63 | "tmachine.progress": "प्रगति", 64 | "tmachine.structureSeedSearchFinished": "सरंचना सीड खोज समाप्त हुयी।", 65 | "tmachine.decoratorWorldSeedSearch": "डेकोरेटर्स से वर्ल्ड सीड खोज रहा है...", 66 | "tmachine.hashedSeedWorldSeedSearch": "हैश हुए सीड से वर्ल्ड सीड खोज रहा है...", 67 | "tmachine.foundWorldSeed": "वर्ल्ड सीड मिल गया ${SEED}.", 68 | "tmachine.worldSeedSearchFinished": "वर्ल्ड सीड के लिए खोज समाप्त हुई।", 69 | "tmachine.noResultsRevertingToBiomes": "खोज बिना परिणामो के समाप्त हुई, बायोम में पूर्ववत किया जा रहा है।", 70 | "tmachine.moreBiomesNeeded": "आपको और अधिक बायोम जानकारी संग्रहित करनी होगी", 71 | "tmachine.biomeWorldSeedSearch": "%s बायोम से वर्ल्ड सीड खोज रहा है", 72 | "tmachine.fuzzyBiomeSearch": "फजी बायोम खोज से प्रयास कर रहा है", 73 | "tmachine.deepBiomeSearch": "डीप बायोम खोज से प्रयास कर रहा है", 74 | "tmachine.printSeedsInConsole": "[स्पैम सुरक्षा] कंसोल में अन्य सभी सीड को प्रिंट कर रहा है", 75 | "tmachine.deleteBiomeInformation": "बायोम जानकारी हटा रहा है चूँकि कोई सीड नहीं मिला", 76 | "tmachine.randomSeedSearch": "उन वर्ल्ड सीड को खोज रहा है जो संभव हैं अगर वर्ल्ड एक यादृच्छिक सीड उपयोग करता है", 77 | "tmachine.startLifting": "%s सरंचनाओँ से उठा रहा है। यह कुछ मिनट ले सकता है", 78 | "tmachine.reduceSeeds": "%s सरंचना सीड घटाया जा रहा है", 79 | "tmachine.succeedReducing": "सीड घटने में असफल", 80 | "tmachine.failedReducing": "सीड घटने में असफल। आपको संभवतया अधिक सरंचनाओं की जरुरत है या आपका देता गलत है", 81 | "dungeon.start": "डंजियन से शॉर्ट कट कर रहा है...", 82 | "dungeon.structureSeedSearchFailed": "बिना कोई सीड के डंजियन खोज पूरी हुई।", 83 | "dungeon.finishedNeedAnotherOne": "सरंचना सीड खोज समाप्त हुई। आपको एक और डंजियन की आवश्यकता है", 84 | "fungus.start": "%s %s पर क्रैकर चला रहा है", 85 | "fungus.fungusSeed": "फंगस सीड: ${SEED}.", 86 | "fungus.wrongData": "कोई फंगस सीड नहीं, फंगस संशोधित हुआ था (जनरेशन के दौरान बदलाव भी सम्मिलित)", 87 | "fungus.noStructureSeedsFound": "इस फंगस के लिए कोई सीड नहीं मिला।", 88 | "fungus.gotStructureSeeds": "सरंचना सीड मिला:", 89 | "fungus.usableAsWorldSeed": "यह सरंचना सीड वर्ल्ड सीड की तरह भी उपयोग किया जा सकता है", 90 | "database.success": "सीड को डेटाबेस में सफलतापूर्वक भेजा गया", 91 | "database.fail": "सीड को डेटाबेस में भेजने में असफल रहा" 92 | } 93 | -------------------------------------------------------------------------------- /src/main/resources/assets/seedcrackerx/lang/ru_ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Seed Cracker X", 3 | "settings": "Настройки", 4 | "settings.active": "Крякер включен?", 5 | "settings.database": "Отправить в базу данных? (Работает если больше 10 игроков на сервере)", 6 | "settings.hideNameDatabase": "Скрыть имя пользователя в базе данных?", 7 | "settings.openDatabase": "Открыть базу данных", 8 | "settings.version": "Версия", 9 | "settings.visuals": "Визуальное оформление", 10 | "settings.outline": "Выделение контуров", 11 | "settings.finderToggles": "Структуры которые будут использоваться для поиска", 12 | "settings.antiXrayMode": "Anti Xray режим", 13 | "settings.antiAntiXrayExplained": "Отправляет пакеты серверу если данж со спаунером состоит не только из обычного и замшелого булыжника. В ответ сервер отправляет реальные блоки. Это может быть замечено очень чувствительными анти-читами, но никто пока не жаловался (версия 2.9.0 имеет эту функцию всегда включенной ~2000 скачиваний). Это делает процесс куда более плавным, поэтому я рекомендую оставлять это включенным", 14 | "finder.buriedTreasures": "Зарытые сокровища", 15 | "finder.desertTemples": "Пустынные пирамиды", 16 | "finder.endCities": "Города края", 17 | "finder.jungleTemples": "Джунглиевые пирамиды", 18 | "finder.monuments": "Подводные монументы", 19 | "finder.swampHuts": "Домики ведьмы", 20 | "finder.shipwrecks": "Кораблекрушения", 21 | "finder.outposts": "Аванпосты разбойников", 22 | "finder.igloo": "Иглу", 23 | "finder.endPillars": "Столбы края (обсидиановые)", 24 | "finder.endGateways": "Шлюзы края", 25 | "finder.dungeons": "Комнаты со спаунерами", 26 | "finder.emeraldOres": "Изумрудная руда", 27 | "finder.desertWells": "Пустынные колодцы", 28 | "finder.warpedFungus": "Искаженные грибы", 29 | "finder.biomes": "Биомы", 30 | "finder.isFinder": "Состояние искателя %s", 31 | "finder.setFinder": "Состояние искателя %s было изменено на", 32 | "info": "Информация", 33 | "info.clearData": "Очистить данные", 34 | "info.worldSeeds": "Сид мира", 35 | "info.noWorldSeeds": "Сид не был найден", 36 | "info.structureSeeds": "Структурный сид", 37 | "info.noStructureSeeds": "Структурные сиды не были найдены", 38 | "info.pillarSeeds": "Сид столбов края (обсидиановых)", 39 | "info.noPillarSeeds": "Сид столбов края (обсидиановых) не был найден", 40 | "info.hashedSeed": "Хешированный сид", 41 | "info.noHashedSeed": "Хешированный сид не был найден", 42 | "fetchedHashedSeed": "Сид в данном измерении отличается от прошлого.", 43 | "foundRestorableStructures": "Найдено %s структур с прошлой сессии. Восстановите их с помощью /seedcracker data restore", 44 | "foundStructureSeed": "Найден структурный сид ${SEED}.", 45 | "finishedSearchNoResult": "Поиск окончен без результатов.", 46 | "crossCompare": "Перекрестно сравниваем сиды и скоращаем ${SEED}.", 47 | "data.clearData": "Очистить данные", 48 | "data.collectedBits": "В данный момент у вас %s битов из %s.", 49 | "data.collectedLiftingBits": "В данный момент у вас %s битов лифтабильных стуктур из %s.", 50 | "data.restoreStructures": "Восстановлено %s структур", 51 | "data.restoreFailed": "Структур с прошлой сессии не было найдено", 52 | "cracker.successfully": "Успешно", 53 | "cracker.already": "уже", 54 | "cracker.enabled": "Включено", 55 | "cracker.disabled": "Выключено", 56 | "render.getRenderMode": "Актуальный режим рендера", 57 | "render.setRenderMode": "Режим рендера сменен на", 58 | "version.setVersion": "Версия изменена на", 59 | "tmachine.lookingForPillarSeed": "Поиск сида столбов края...", 60 | "tmachine.foundPillarSeed": "Сид столбов края найден ${SEED}.", 61 | "tmachine.pillarSeedSearchFinished": "Поиск сида столбов края завершен.", 62 | "tmachine.lookingForStructureSeeds": "Поиск структурного сида используя сид стобов края [%s]...", 63 | "tmachine.progress": "Прогресс", 64 | "tmachine.structureSeedSearchFinished": "Поиск структурного сида завершен.", 65 | "tmachine.decoratorWorldSeedSearch": "Поиск сида по декораторам...", 66 | "tmachine.hashedSeedWorldSeedSearch": "Поиск сида по хешированному сиду......", 67 | "tmachine.foundWorldSeed": "Сид мира найден ${SEED}.", 68 | "tmachine.worldSeedSearchFinished": "Поиск сида завершен.", 69 | "tmachine.noResultsRevertingToBiomes": "Поиск сида завершен без результатов, возвращаемся к биомам.", 70 | "tmachine.moreBiomesNeeded": "Вам необходимо собрать больше данных о биомах", 71 | "tmachine.biomeWorldSeedSearch": "Поиск сида используя %s биомов...", 72 | "tmachine.fuzzyBiomeSearch": "Пытаюсь выполнить поиск по нечеткому биому", 73 | "tmachine.deepBiomeSearch": "Попытка глубокого поиска по биомам", 74 | "tmachine.printSeedsInConsole": "[Защита от спама] вывод всех других структурных сидов в консоль", 75 | "tmachine.deleteBiomeInformation": "Удаление информации по биомам т.к не один сид не был найден", 76 | "tmachine.randomSeedSearch": "Поиск сида мира если мир использует случайный сид", 77 | "tmachine.startLifting": "Начинаем лифтинг используя %s структур. Это займет несколько минут", 78 | "tmachine.reduceSeeds": "Сокращаем %s структурных сидов", 79 | "tmachine.succeedReducing": "Уменьшено до %s структурных сидов", 80 | "tmachine.failedReducing": "Не получилось уменьшить количество структурных сидов. Вам нужно найти больше структрур, или же ваши данные повреждены", 81 | "dungeon.start": "Сокращение подземелий...", 82 | "dungeon.structureSeedSearchFailed": "Поиск по подземельям неудачен.", 83 | "dungeon.finishedNeedAnotherOne": "Поиск сида подземелья завершен. Вам нужно другое подземелье", 84 | "fungus.start": "использование крекера на %s %s", 85 | "fungus.fungusSeed": "Сид искаженного гриба: ${SEED}.", 86 | "fungus.wrongData": "Сид искаженного гриба не найден, он был изменен (так-же включает в себя изменения при генерации)", 87 | "fungus.noStructureSeedsFound": "Сид для этого искаженного гриба не найден.", 88 | "fungus.gotStructureSeeds": "найден структурный сид:", 89 | "fungus.usableAsWorldSeed": "этот структурный сид используется как сид мира", 90 | "database.success": "успешная отправка сида в базу данных", 91 | "database.fail": "провальная отправка сида в базу данных" 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/resources/assets/seedcrackerx/lang/tr_tr.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Seed Cracker X", 3 | "settings": "Ayarlar", 4 | "settings.active": "Aktif", 5 | "settings.database": "10+ üstü oyuncu bulunan sunucu seed'lerini veri tabanına gönder", 6 | "settings.hideNameDatabase": "Veri tabanında kullanıcı adlarını gizle", 7 | "settings.openDatabase": "Veri tabanı'nı aç", 8 | "settings.version": "Sürüm", 9 | "settings.visuals": "Görseller", 10 | "settings.outline": "Dış çizgileri göster", 11 | "settings.finderToggles": "Arayıcı ayarları", 12 | "settings.antiXrayMode": "Anti Xray Modu", 13 | "settings.antiAntiXrayExplained": "Eğer Tapınak tabanı sadece kırıktaş ve yosunlu kırıktaş değilse sunucuya paket gönderir. Cevap olarak sunucu, gerçek blokları söyler. Bu işlem hassas hile korumalarını tetikleyebilir fakat şu ana kadar kimse ban/kick şikayeti iletmedi (2.9.0 sürümünde bu özellik hep açık ve ~2000 indirmeye sahip). Bu ayar, işlemi çok daha hafif hale getirir bu yüzden açık tutmanızı öneririm.", 14 | "finder.buriedTreasures": "Gömülü hazineler", 15 | "finder.desertTemples": "Çöl tapınakları", 16 | "finder.endCities": "End şehirleri", 17 | "finder.jungleTemples": "Orman tapınakları", 18 | "finder.monuments": "Okyanus mabetleri", 19 | "finder.swampHuts": "Cadı kulübeleri", 20 | "finder.shipwrecks": "Gemi enkazları", 21 | "finder.outposts": "Pillager mıntıkaları", 22 | "finder.igloo": "İglolar", 23 | "finder.endPillars": "End kuleleri", 24 | "finder.endGateways": "End geçitleri", 25 | "finder.dungeons": "Zindanlar", 26 | "finder.emeraldOres": "Zümrüt cevherleri", 27 | "finder.desertWells": "Çöl kuyuları", 28 | "finder.warpedFungus": "Eğri mantar", 29 | "finder.biomes": "Biyomlar", 30 | "finder.isFinder": "Arayıcı %s şuna ayarlı", 31 | "finder.setFinder": "Arayıcı %s şuna ayarlandı", 32 | "info": "Bilgi", 33 | "info.clearData": "Verileri temizle", 34 | "info.worldSeeds": "Dünya seed'leri", 35 | "info.noWorldSeeds": "Hiç dünya seed'i bulunamadı", 36 | "info.structureSeeds": "Yapı seed'leri", 37 | "info.noStructureSeeds": "Hiç yapı seed'i bulunamadı", 38 | "info.pillarSeeds": "Kule seed'leri", 39 | "info.noPillarSeeds": "Hiç kule seed'i bulunamadı", 40 | "info.hashedSeed": "Hash'lanmış seed", 41 | "info.noHashedSeed": "Hiç hash'lanmış seed bulunamadı", 42 | "fetchedHashedSeed": "Bu boyutta dünya seed'i farklı", 43 | "foundRestorableStructures": "Önceki oturumdan %s yapı(lar) bulundu. Şu komut ile kurtarın: /seedcracker data restore", 44 | "foundStructureSeed": "Yapı seed'i bulundu: ${SEED}", 45 | "finishedSearchNoResult": "Arama sonuç bulunamadan tamamlandı.", 46 | "crossCompare": "Seed'ler çapraz-karşılaştırma ile karşılaştırıldı ve ${SEED}'a azaltıldı", 47 | "data.clearData": "Veri deposu temizlendi", 48 | "data.collectedBits": "Şu ana kadar %s bit veri topladın (%s bit içerisinden).", 49 | "data.collectedLiftingBits": "Şu an kaldırılabilir yapılardan %s bit topladın (%s bit içerisinden)", 50 | "data.restoreStructures": "%s adet yapı kurtarıldı", 51 | "data.restoreFailed": "Önceki oturumdan hiç yapı bulunamadı", 52 | "cracker.successfully": "Başarılı ", 53 | "cracker.already": "zaten ", 54 | "cracker.enabled": "etkin", 55 | "cracker.disabled": "etkin değil", 56 | "render.getRenderMode": "Render modu şuna ayarlı", 57 | "render.setRenderMode": "Render modu ayarlandı", 58 | "version.setVersion": "Sürüö şuna ayarlandı:", 59 | "tmachine.lookingForPillarSeed": "Kule seed'leri aranıyor...", 60 | "tmachine.foundPillarSeed": "Kule seedi bulundu: ${SEED}", 61 | "tmachine.pillarSeedSearchFinished": "Kule seed'i arama işlemi bitirildi.", 62 | "tmachine.lookingForStructureSeeds": "Kule seed'i [%s] ile yapı seedleri aranıyor...", 63 | "tmachine.progress": "İlerleme", 64 | "tmachine.structureSeedSearchFinished": "Yapı seed'leri arama işlemi bitti.", 65 | "tmachine.decoratorWorldSeedSearch": "Dekoratörler ile dünya seed'leri aranıyor...", 66 | "tmachine.hashedSeedWorldSeedSearch": "Hash'lanmış seed ile dünya seedleri aranıyor...", 67 | "tmachine.foundWorldSeed": "Dünya seedi bulundu: ${SEED}", 68 | "tmachine.worldSeedSearchFinished": "Dünya seed'leri arama işlemi bitti.", 69 | "tmachine.noResultsRevertingToBiomes": "Arama işleminde sonuç bulunamadı, Biyom'a geri dönülüyor.", 70 | "tmachine.moreBiomesNeeded": "Daha fazla biyom bilgisi toplaman lazım.", 71 | "tmachine.biomeWorldSeedSearch": "%s biyom ile dünya seed'leri aranıyor...", 72 | "tmachine.fuzzyBiomeSearch": "Basit biyom arama işlemi deneniyor", 73 | "tmachine.deepBiomeSearch": "Detaylı biyom arama işlemi deneniyor", 74 | "tmachine.printSeedsInConsole": "[Spam Koruması] Diğer tüm seed'ler konsola yazdırılıyor", 75 | "tmachine.deleteBiomeInformation": "Eşleşen seed bulunamadığı için biyom bilgisi siliniyor", 76 | "tmachine.randomSeedSearch": "Dünya rastgele seed kullanıyorsa oluşabilecek seed'ler aranıyor", 77 | "tmachine.startLifting": "%s yapı ile kaldırılmaya başlandı. Bu işlem bir kaç dakika sürer", 78 | "tmachine.reduceSeeds": "%s yapı seed'i azaltılıyor", 79 | "tmachine.succeedReducing": "%s yapı seed'ine azaltıldı", 80 | "tmachine.failedReducing": "Seed'ler azaltılamadı. Muhtemelen daha çok yapıya ihtiyacınız var yada veriniz yanlış", 81 | "dungeon.start": "Zindan'a kısayol oluşturuluyor...", 82 | "dungeon.structureSeedSearchFailed": "Zindan aramasından sonuç bulunamadı.", 83 | "dungeon.finishedNeedAnotherOne": "yapı seed'i araması bitirildi. Başka bir zindana ihtiyacın var", 84 | "fungus.start": "Arayıcı %s %s'da çalıştırılıyor", 85 | "fungus.fungusSeed": "mantar seed'i: ${SEED}.", 86 | "fungus.wrongData": "Mantar seed'i yok, mantar değiştirilmiş (Oluşum aşamasında değişimler de olabilir)", 87 | "fungus.noStructureSeedsFound": "Bu mantar için hiç seed bulunamadı", 88 | "fungus.gotStructureSeeds": "Yapı seed'leri bulundu:", 89 | "fungus.usableAsWorldSeed": "bu yapı seed'i dünya seed'i olarak da kullanılabilir", 90 | "database.success": "seed veri tabanına başarıyla iletildi", 91 | "database.fail": "seed veri tabanına iletilemedi" 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/resources/assets/seedcrackerx/lang/zh_cn.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Seed Cracker X", 3 | "settings": "设置", 4 | "settings.active": "激活", 5 | "settings.database": "把有10+玩家的服务器的种子发送到数据库", 6 | "settings.hideNameDatabase": "在种子数据库中隐藏用户名", 7 | "settings.openDatabase": "打开数据库", 8 | "settings.version": "版本", 9 | "settings.visuals": "视觉效果", 10 | "settings.outline": "渲染轮廓", 11 | "settings.finderToggles": "切换查找器", 12 | "settings.antiXrayMode": "绕过反矿透模式", 13 | "settings.antiAntiXrayExplained": "如果地牢的地板不只有圆石和苔石,则向服务器发送数据包。作为回应,服务器会告诉客户端真正的区块。这可能会触发超级严格的反作弊,但还没有人抱怨被封禁/踢出服务器(2.9.0版本一直有这个功能,目前有~2000次下载)。它使整个过程更加顺畅,因此我强烈建议将其打开", 14 | "finder.buriedTreasures": "埋藏的宝藏", 15 | "finder.desertTemples": "沙漠神殿", 16 | "finder.endCities": "末地城", 17 | "finder.jungleTemples": "丛林神庙", 18 | "finder.monuments": "海底神殿", 19 | "finder.swampHuts": "沼泽小屋", 20 | "finder.shipwrecks": "沉船", 21 | "finder.outposts": "掠夺者前哨站", 22 | "finder.igloo": "雪屋", 23 | "finder.endPillars": "黑曜石柱", 24 | "finder.endGateways": "末地折跃门", 25 | "finder.dungeons": "地牢", 26 | "finder.emeraldOres": "绿宝石矿石", 27 | "finder.desertWells": "沙漠水井", 28 | "finder.warpedFungus": "诡异菌", 29 | "finder.biomes": "生物群系", 30 | "finder.isFinder": "查找器 %s 被设置为", 31 | "finder.setFinder": "查找器 %s 已被设置为", 32 | "info": "信息", 33 | "info.clearData": "清除数据", 34 | "info.worldSeeds": "世界种子", 35 | "info.noWorldSeeds": "没有找到世界种子", 36 | "info.structureSeeds": "结构种子", 37 | "info.noStructureSeeds": "没有找到结构种子", 38 | "info.pillarSeeds": "黑曜石柱的种子", 39 | "info.noPillarSeeds": "没有找到黑曜石柱的种子", 40 | "info.hashedSeed": "散列化的种子", 41 | "info.noHashedSeed": "没有找到散列化的种子", 42 | "fetchedHashedSeed": "获取散列化的世界种子", 43 | "foundRestorableStructures": "找到了前一个会话中的 %s 结构。用/seedcracker data restore来恢复它们", 44 | "foundStructureSeed": "发现结构种子 ${SEED}", 45 | "finishedSearchNoResult": "搜索完成,无结果。", 46 | "crossCompare": "交叉比较了种子,并还原为${SEED}。", 47 | "data.clearData": "清除了数据存储", 48 | "data.collectedBits": "您当前已收集了 %s 位从 %s 位中。", 49 | "data.collectedLiftingBits": "您当前已收集了 %s 位从 %s 位的可挖掘结构中。", 50 | "data.restoreStructures": "恢复了 %s 结构", 51 | "data.restoreFailed": "没有发现前一个会话的结构", 52 | "cracker.successfully": "成功 ", 53 | "cracker.already": "已经 ", 54 | "cracker.enabled": "启用", 55 | "cracker.disabled": "禁用", 56 | "render.getRenderMode": "当前的渲染模式被设置为", 57 | "render.setRenderMode": "改变渲染模式为", 58 | "version.setVersion": "改变版本为", 59 | "tmachine.lookingForPillarSeed": "正在搜索黑曜石柱种子...", 60 | "tmachine.foundPillarSeed": "发现黑曜石柱种子 ${SEED}。", 61 | "tmachine.pillarSeedSearchFinished": "完成了黑曜石柱种子的搜索。", 62 | "tmachine.lookingForStructureSeeds": "正在搜索带有黑曜石柱种子[%s]的结构种子...", 63 | "tmachine.progress": "进度", 64 | "tmachine.structureSeedSearchFinished": "完成了对结构种子的搜索。", 65 | "tmachine.decoratorWorldSeedSearch": "正在用装饰搜索世界种子...", 66 | "tmachine.hashedSeedWorldSeedSearch": "正在搜索世界种子...", 67 | "tmachine.foundWorldSeed": "发现世界种子${SEED}。", 68 | "tmachine.worldSeedSearchFinished": "完成了对世界种子的搜索。", 69 | "tmachine.noResultsRevertingToBiomes": "完成了搜索,没有结果,重新回到生物群系。", 70 | "tmachine.moreBiomesNeeded": "你需要收集更多的生物群系信息", 71 | "tmachine.biomeWorldSeedSearch": "搜索具有%s生物群系的世界种子...", 72 | "tmachine.fuzzyBiomeSearch": "尝试模糊的生物群系搜索", 73 | "tmachine.deepBiomeSearch": "尝试深度生物群系搜索", 74 | "tmachine.printSeedsInConsole": "[防刷屏]在控制台输出所有其他种子", 75 | "tmachine.deleteBiomeInformation": "删除生物群系信息,因为没有找到匹配的种子", 76 | "tmachine.randomSeedSearch": "如果世界使用随机种子,则搜索可能的世界种子", 77 | "tmachine.startLifting": "用 %s 个结构开始挖掘。这可能要花费几分钟。", 78 | "tmachine.reduceSeeds":"减少结构种子", 79 | "tmachine.succeedReducing": "减少到了 %s 个结构种子", 80 | "tmachine.failedReducing": "无法减少种子", 81 | "dungeon.start": "开始搜索地牢...", 82 | "dungeon.structureSeedSearchFailed": "完成了地牢搜索,没有找到种子,", 83 | "dungeon.finishedNeedAnotherOne": "完成了地牢搜索。你需要另一个地牢", 84 | "fungus.start": "在 %s %s 运行搜索器", 85 | "fungus.fungusSeed": "菌类种子:${SEED}", 86 | "fungus.wrongData": "没有菌类种子,菌类被修改了(也包括生成过程中的变化)", 87 | "fungus.noStructureSeedsFound": "没有找到这个菌类的种子。", 88 | "fungus.gotStructureSeeds": "找到了结构种子:", 89 | "fungus.usableAsWorldSeed": "这个结构种子也可用作世界种子", 90 | "database.success": "发送成功", 91 | "database.fail": "发送失败" 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/resources/assets/seedcrackerx/shaders/core/rendertype_lines.fsh: -------------------------------------------------------------------------------- 1 | #version 150 2 | 3 | uniform vec4 ColorModulator; 4 | 5 | in float vertexDistance; 6 | in vec4 vertexColor; 7 | 8 | out vec4 fragColor; 9 | 10 | void main() { 11 | vec4 color = vertexColor * ColorModulator; 12 | fragColor = color; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "seedcrackerx", 4 | "version": "${version}", 5 | "name": "SeedCrackerX", 6 | "description": "Used for finding the seed of multiplayer or singleplayer worlds.", 7 | "authors": [ 8 | "KaptainWutax", 9 | "19MisterX98" 10 | ], 11 | "contact": { 12 | "issues": "https://github.com/19MisterX98/SeedcrackerX/issues", 13 | "sources": "https://github.com/19MisterX98/seedcrackerX/" 14 | }, 15 | "license": "MIT", 16 | "icon": "assets/seedcrackerx/icon.png", 17 | "environment": "client", 18 | "entrypoints": { 19 | "main": [ 20 | "kaptainwutax.seedcrackerX.SeedCracker" 21 | ], 22 | "modmenu": [ 23 | "kaptainwutax.seedcrackerX.config.ScModMenuEntry" 24 | ] 25 | }, 26 | "mixins": [ 27 | "seedcracker.mixins.json" 28 | ], 29 | "depends": { 30 | "fabricloader": ">=${loader_version}", 31 | "minecraft": ">=1.21.5 <1.22", 32 | "fabric-api-base": "*", 33 | "fabric-command-api-v2": "*", 34 | "fabric-rendering-v1": "*", 35 | "fabric-resource-loader-v0": "*", 36 | "cloth-config": "*" 37 | }, 38 | "suggests": { 39 | "flamingo": "*", 40 | "modmenu": "*" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/resources/seedcracker.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "minVersion": "0.8", 4 | "package": "kaptainwutax.seedcrackerX.mixin", 5 | "compatibilityLevel": "JAVA_17", 6 | "mixins": [ 7 | ], 8 | "client": [ 9 | "ClientPlayerEntityMixin", 10 | "ClientPlayNetworkHandlerMixin", 11 | "ClientWorldMixin" 12 | ], 13 | "injectors": { 14 | "defaultRequire": 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /taskBuild.bat: -------------------------------------------------------------------------------- 1 | gradlew build -------------------------------------------------------------------------------- /taskSetup.bat: -------------------------------------------------------------------------------- 1 | gradlew genSources idea --------------------------------------------------------------------------------