├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src └── main ├── java └── supercoder79 │ └── simplexterrain │ ├── SimplexTerrain.java │ ├── api │ ├── BackingBiomeSource.java │ ├── Coordinate2Function.java │ ├── Heightmap.java │ ├── biomes │ │ ├── OceanSet.java │ │ ├── SimplexBiomes.java │ │ ├── SimplexClimate.java │ │ ├── SimplexNether.java │ │ └── SquareCrossSamplingLayer.java │ ├── noise │ │ ├── Noise.java │ │ ├── NoiseType.java │ │ └── OctaveNoiseSampler.java │ ├── noisemodifier │ │ └── NoiseModifier.java │ └── postprocess │ │ ├── PostProcessorTarget.java │ │ └── TerrainPostProcessor.java │ ├── client │ └── GoVote.java │ ├── command │ ├── MapHeightmapCommand.java │ ├── MapNoiseTypeCommand.java │ └── ReloadConfigCommand.java │ ├── compat │ ├── Compat.java │ └── VanillaBiomes.java │ ├── configs │ ├── ConfigHelper.java │ ├── MainConfigData.java │ ├── noisemodifiers │ │ ├── DetailsConfigData.java │ │ ├── MountainConfigData.java │ │ ├── MushroomFieldsConfigData.java │ │ ├── PlateausConfigData.java │ │ ├── RidgesConfigData.java │ │ └── RiversConfigData.java │ └── postprocessors │ │ ├── CaveConfigData.java │ │ ├── ErosionConfigData.java │ │ ├── RiverConfigData.java │ │ └── SoilConfigData.java │ ├── mixin │ ├── MixinChunkStatus.java │ ├── MixinGeneratorOptions.java │ ├── MixinMinecraftServer.java │ ├── MixinNoiseChunkGenerator.java │ ├── MixinSpawnLocating.java │ ├── antibad │ │ └── MixinLakeFeature.java │ ├── client │ │ ├── MixinMinecraftClient.java │ │ └── MixinSkyProperties.java │ └── optichunk │ │ └── MixinChunkSection.java │ ├── noise │ ├── NoiseMath.java │ ├── gradient │ │ ├── CubicNoise.java │ │ ├── GaborNoise.java │ │ ├── OpenSimplexNoise.java │ │ ├── PerlinNoise.java │ │ └── SimplexStyleNoise.java │ ├── notch │ │ └── NoiseMap.java │ ├── value │ │ └── ValueNoise.java │ ├── voronoi │ │ └── VoronoiNoise.java │ └── worley │ │ ├── WorleyNoise.java │ │ └── XorShift.java │ └── world │ ├── BiomeData.java │ ├── README.md │ ├── SimplexWorldType.java │ ├── biome │ ├── BiomePicker.java │ └── SimplexBiomesImpl.java │ ├── biomelayers │ ├── SimplexBiomeLayers.java │ └── layers │ │ ├── BaseBiomesLayer.java │ │ ├── ClimateTransformerLayer.java │ │ └── SimplexClimateLayer.java │ ├── blend │ ├── CachingBlender.java │ ├── ChunkPointGatherer.java │ ├── GatheredPoint.java │ ├── LinkedBiomeWeightMap.java │ ├── ScatteredBiomeBlender.java │ └── UnfilteredPointGatherer.java │ ├── gen │ ├── ContinentCache.java │ ├── ContinentGenerator.java │ ├── SimplexBiomeSource.java │ ├── SimplexChunkGenerator.java │ └── SimplexNetherGeneration.java │ ├── noisemodifier │ ├── DetailNoiseModifier.java │ ├── MountainsNoiseModifier.java │ ├── MushroomIslandsNoiseModifier.java │ ├── NoiseModifiers.java │ ├── PlateausNoiseModifier.java │ ├── RidgesNoiseModifier.java │ └── RiversNoiseModifier.java │ ├── noisetype │ ├── DefaultNoiseType.java │ ├── NoiseType.java │ ├── NoiseTypeCache.java │ ├── NoiseTypeHolder.java │ ├── NoiseTypePicker.java │ ├── desert │ │ ├── DunesNoiseType.java │ │ └── SavannaHillsNoiseType.java │ ├── forest │ │ └── HillsNoiseType.java │ └── plains │ │ ├── ForestedHillsNoiseType.java │ │ ├── LowLyingPlainsNoiseType.java │ │ ├── MountainsNoiseType.java │ │ └── PlainsNoiseType.java │ └── postprocessor │ ├── ErosionPostProcessor.java │ ├── OldRiverPostProcessor.java │ ├── PostProcessors.java │ ├── SimplexCavesPostProcessor.java │ ├── SoilPostProcessor.java │ └── StrataPostProcessor.java └── resources ├── assets └── simplexterrain │ ├── icon.png │ └── lang │ └── en_us.json ├── fabric.mod.json ├── simplexterrain.aw └── simplexterrain.mixins.json /.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 | # eclipse 24 | *.launch 25 | 26 | # fabric 27 | 28 | logs/ 29 | run/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simplex Terrain 2 | Makes new terrain with multiple octaves of simplex noise! 3 | 4 | ## What is Simplex Terrain Generation? 5 | Simplex Terrain Generation is a world generation mod focused on giving users the ability to extensively customize the terrain generation and generating that terrain quickly. 6 | To use Simplex Terrain Generation, select the world type `Simplex Terrain` when making a new world. Server owners will want to put `simplex` as the level type in server.properties. Simplex Terrain Generation 0.4.0+ requires Fabric API. 7 | 8 | ## Configuration 9 | When launching the game for the first time, you will get a new file in your config folder called simplexterrain.json. In that you will find a plethora of values to tweak your terrain generation. Play around with it and find what suits you best! 10 | The config file is documented [here!](https://github.com/SuperCoder7979/simplexterrain/wiki/Config-Documentation) 11 | Here are some really cool [config presets](https://github.com/SuperCoder7979/simplexterrain/wiki/Config-Presets) for you to use! 12 | Different noise algorithms that you can use are covered in detail [here!](https://github.com/SuperCoder7979/simplexterrain/wiki/Noise-Implementations) 13 | 14 | ## Discord server 15 | Join our **Discord server** https://discord.gg/BuBGds9 to get the latest updates on what we're doing, to get help, or to simply talk about the cool words that you've made! If you'd like to help contribute, please contact us here. 16 | 17 | ## Want to support development? 18 | Please consider supporting development via my [Patreon](https://www.patreon.com/supercoder79)! Supporting me through Patreon allows me to spend more time modding and put out more updates for everyone. 19 | 20 | ## Specific Implementation Details 21 | Simplex Terrain Generation uses a heightmap made out of simplex noise, normalized to fit between 256 and 0. This heightmap is used to place the actual blocks and to place the biomes. The biomes are placed in 7 distinct "regions", to make the terrain more natural. Here's a list of them: 22 | 23 | Y0 - Y29: All variants of deep ocean 24 | Y30 - Y60: All variants of ocean 25 | Y63 - Y66: Beach 26 | From Y67 onwards, biome generation is split into 4 different regions based on height (Y67 - Y90, Y91 - Y140, Y141 - Y190, Y191 - Y256). The biomes can vary, but generally become colder as the height increases. If you would like to increase the amount of cold/hot biomes, a config for that will be available in 0.5.0 (unreleased at time of writing). If you want to change the heights that these regions start at, take a look at the config! 27 | 28 | ## Images 29 | Savanna generation: 30 | ![](https://cdn.discordapp.com/attachments/651608036774903844/768957064947957861/unknown.png "") 31 | Ridged mountain: 32 | ![](https://cdn.discordapp.com/attachments/688776607049187444/721351747247013898/unknown.png) 33 | River generation: 34 | ![](https://cdn.discordapp.com/attachments/688776607049187444/771041441786101811/unknown.png) 35 | Snowy biome: 36 | ![](https://cdn.discordapp.com/attachments/688776607049187444/771041498086899782/unknown.png) 37 | 38 | ## Credits 39 | 40 | SuperCoder79 - Breaks everything 41 | Valoeghese - World Generation Magician 42 | 43 | ## YourKit 44 | ![](https://www.yourkit.com/images/yklogo.png) 45 | Yourkit helps Simplex Terrain optimize and profile code, to ensure it's always fast. 46 | 47 | YourKit supports open source projects with innovative and intelligent tools 48 | for monitoring and profiling Java and .NET applications. YourKit is the creator of [YourKit Java Profiler](https://www.yourkit.com/java/profiler/), [YourKit .NET Profiler](https://www.yourkit.com/.net/profiler/), and [YourKit YouMonitor](https://www.yourkit.com/youmonitor/). 49 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'fabric-loom' version '0.7-SNAPSHOT' 3 | id 'maven-publish' 4 | } 5 | 6 | sourceCompatibility = JavaVersion.VERSION_1_8 7 | targetCompatibility = JavaVersion.VERSION_1_8 8 | 9 | archivesBaseName = project.archives_base_name 10 | version = project.mod_version 11 | group = project.maven_group 12 | 13 | minecraft { 14 | accessWidener = file("src/main/resources/simplexterrain.aw") 15 | } 16 | 17 | repositories { 18 | mavenLocal() 19 | maven { url = "https://jitpack.io" } 20 | } 21 | 22 | dependencies { 23 | //to change the versions see the gradle.properties file 24 | minecraft "com.mojang:minecraft:${project.minecraft_version}" 25 | mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" 26 | modCompile "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" 27 | modCompile "net.fabricmc:fabric-loader:${project.loader_version}" 28 | 29 | modRuntime ("com.github.SuperCoder7979:databreaker:0.2.6") { 30 | exclude module : "fabric-loader" 31 | } 32 | 33 | // modRuntime ("com.github.mrmangohands:sodium-fabric:88bdab9e72bde91580715a82d2e523f58a3ba6b0") 34 | // modRuntime ("com.github.jellysquid3:phosphor-fabric:0749029a498e8f6574643285bae7aecb2eda76b8") 35 | // modRuntime ("com.github.jellysquid3:lithium-fabric:fa7e919133d6dd9f1166a054aab3ff275fc4de4d") 36 | // modRuntime ("com.github.TerraformersMC:Traverse:01f9e10b88251b70cfecf83695f4cc652ddef805") 37 | 38 | // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. 39 | // You may need to force-disable transitiveness on them. 40 | } 41 | 42 | processResources { 43 | inputs.property "version", project.version 44 | 45 | from(sourceSets.main.resources.srcDirs) { 46 | include "fabric.mod.json" 47 | expand "version": project.version 48 | } 49 | 50 | from(sourceSets.main.resources.srcDirs) { 51 | exclude "fabric.mod.json" 52 | } 53 | } 54 | 55 | // ensure that the encoding is set to UTF-8, no matter what the system default is 56 | // this fixes some edge cases with special characters not displaying correctly 57 | // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html 58 | tasks.withType(JavaCompile) { 59 | options.encoding = "UTF-8" 60 | } 61 | 62 | // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task 63 | // if it is present. 64 | // If you remove this task, sources will not be generated. 65 | task sourcesJar(type: Jar, dependsOn: classes) { 66 | classifier = "sources" 67 | from sourceSets.main.allSource 68 | } 69 | 70 | jar { 71 | from "LICENSE" 72 | } 73 | 74 | // configure the maven publication 75 | publishing { 76 | publications { 77 | mavenJava(MavenPublication) { 78 | // add all the jars that should be included when publishing to maven 79 | artifact(remapJar) { 80 | builtBy remapJar 81 | } 82 | artifact(sourcesJar) { 83 | builtBy remapSourcesJar 84 | } 85 | } 86 | } 87 | 88 | // select the repositories you want to publish to 89 | repositories { 90 | // uncomment to publish to the local maven 91 | // mavenLocal() 92 | } 93 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Done to increase the memory available to gradle. 2 | org.gradle.jvmargs=-Xmx1G 3 | 4 | # Fabric Properties 5 | # check these on https://modmuss50.me/fabric.html 6 | minecraft_version=21w03a 7 | yarn_mappings=21w03a+build.12 8 | loader_version=0.11.1 9 | 10 | #Fabric api 11 | fabric_version=0.29.5+1.17 12 | 13 | # Mod Properties 14 | mod_version = 0.7.2 15 | maven_group = supercoder79.simplexterrain 16 | archives_base_name = simplexterrain -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaskarth/simplexterrain/39d74e99bf060741b40bede9ba3a57ae7fced6b4/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-5.5.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin, switch paths to Windows format before running java 129 | if $cygwin ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | jcenter() 4 | maven { 5 | name = 'Fabric' 6 | url = 'https://maven.fabricmc.net/' 7 | } 8 | gradlePluginPortal() 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/BackingBiomeSource.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api; 2 | 3 | import net.minecraft.util.registry.RegistryKey; 4 | import net.minecraft.world.biome.Biome; 5 | 6 | public interface BackingBiomeSource { 7 | RegistryKey getBacking(int x, int z); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/Coordinate2Function.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api; 2 | 3 | public interface Coordinate2Function { 4 | T apply(int x, int z); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/Heightmap.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api; 2 | 3 | import net.minecraft.util.math.ChunkPos; 4 | import supercoder79.simplexterrain.world.BiomeData; 5 | import supercoder79.simplexterrain.world.gen.SimplexChunkGenerator; 6 | 7 | /** 8 | * Any object that's able to retrieve a height from a heightmap. 9 | * 10 | * @author Valoeghese and SuperCoder79 11 | */ 12 | public interface Heightmap { 13 | /** 14 | * Returns a height value for a x/z coordinate. 15 | * 16 | * When iterating over a chunk to get all of the height values, it is almost always preferable to use 17 | * getHeightInChunk() instead. 18 | * 19 | * @param x x value (block position) 20 | * @param z z value (block position) 21 | * @return The height value of the heightmap at this x/z coordinate. 22 | */ 23 | int getHeight(int x, int z); 24 | 25 | /** 26 | * Returns all of the heights for ever block in this chunk. 27 | * 28 | * The default implementation is good enough but ideally it would be threaded and use a cache to reduce 29 | * access times. {@link SimplexChunkGenerator} 30 | * 31 | * @param pos the position of the requested chunk 32 | * @return an int array of the height values for this chunk. 33 | */ 34 | default int[] getHeightsInChunk(ChunkPos pos) { 35 | int[] heights = new int[256]; 36 | for (int x = 0; x < 16; x++) { 37 | for (int z = 0; z < 16; z++) { 38 | heights[x*16 + z] = getHeight((pos.x * 16) + x, (pos.z * 16) + z); 39 | } 40 | } 41 | return heights; 42 | } 43 | 44 | default BiomeData getBiomeData(int x, int z) { 45 | BiomeData data = new BiomeData(); 46 | data.setHeight(this.getHeight(x, z)); 47 | 48 | return data; 49 | } 50 | 51 | /** 52 | * A heightmap that always returns 0. Useful for a default initialization. 53 | */ 54 | Heightmap NONE = (x, z) -> 0; 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/biomes/OceanSet.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api.biomes; 2 | 3 | import net.minecraft.util.Identifier; 4 | import net.minecraft.world.biome.Biome; 5 | import net.minecraft.world.biome.BiomeKeys; 6 | 7 | public enum OceanSet { 8 | TROPICAL(BiomeKeys.BEACH.getValue(), BiomeKeys.WARM_OCEAN.getValue(), BiomeKeys.DEEP_WARM_OCEAN.getValue()), 9 | TEMPERATE(BiomeKeys.BEACH.getValue(), BiomeKeys.OCEAN.getValue(), BiomeKeys.DEEP_OCEAN.getValue()), 10 | COLD(BiomeKeys.BEACH.getValue(), BiomeKeys.COLD_OCEAN.getValue(), BiomeKeys.DEEP_COLD_OCEAN.getValue()), 11 | FROZEN(BiomeKeys.SNOWY_BEACH.getValue(), BiomeKeys.FROZEN_OCEAN.getValue(), BiomeKeys.DEEP_FROZEN_OCEAN.getValue()); 12 | 13 | public final Identifier shore, ocean, deepOcean; 14 | 15 | OceanSet(Identifier shore, Identifier ocean, Identifier deepOcean) { 16 | this.shore = shore; 17 | this.ocean = ocean; 18 | this.deepOcean = deepOcean; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/biomes/SimplexBiomes.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api.biomes; 2 | 3 | import net.minecraft.util.Identifier; 4 | import supercoder79.simplexterrain.world.biome.SimplexBiomesImpl; 5 | 6 | /** 7 | * API front for Simplex Biomes generator 8 | * 9 | * @author Valoeghese and Supercoder79 10 | */ 11 | public final class SimplexBiomes { 12 | private SimplexBiomes() { 13 | } 14 | 15 | public static void addLowlandsBiome(Identifier biome, SimplexClimate climate, double weight) { 16 | SimplexBiomesImpl.addToLowlands(biome, climate, weight); 17 | } 18 | 19 | public static void addMidlandsBiome(Identifier biome, SimplexClimate climate, double weight) { 20 | SimplexBiomesImpl.addToMidlands(biome, climate, weight); 21 | } 22 | 23 | public static void addHighlandsBiome(Identifier biome, SimplexClimate climate, double weight) { 24 | SimplexBiomesImpl.addToHighlands(biome, climate, weight); 25 | } 26 | 27 | public static void addMountainPeaksBiome(Identifier biome, SimplexClimate climate, double weight) { 28 | SimplexBiomesImpl.addToMountainPeaks(biome, climate, weight); 29 | } 30 | 31 | public static void addReplacementBiome(Identifier biomeToReplace, Identifier replacement, int chance) { 32 | SimplexBiomesImpl.addReplacementBiome(biomeToReplace, replacement, chance); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/biomes/SimplexClimate.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api.biomes; 2 | 3 | import supercoder79.simplexterrain.world.biomelayers.layers.SimplexClimateLayer; 4 | 5 | /** 6 | * Specifies the climates used to determine the biomes. 7 | * It's basically just a couple of if statements with values fed in from simplex noise. 8 | * 9 | * @author Valoeghese 10 | */ 11 | public enum SimplexClimate { 12 | //lush: humidity > 0.3 13 | //dry: humidity < -0.3 14 | //normal: between -0.3 and 0.3 15 | 16 | // temp above 0.28 17 | LUSH_TROPICAL(0, OceanSet.TROPICAL), 18 | TROPICAL(1, OceanSet.TROPICAL), 19 | DRY_TROPICAL(2, OceanSet.TROPICAL), 20 | 21 | // temp between -0.28 and 0.28 22 | LUSH_TEMPERATE(3, OceanSet.TEMPERATE), 23 | TEMPERATE(4, OceanSet.TEMPERATE), 24 | DRY_TEMPERATE(5, OceanSet.TEMPERATE), 25 | 26 | // temp between -0.58 and -0.28 27 | LUSH_BOREAL(6, OceanSet.COLD), 28 | BOREAL(7, OceanSet.COLD), 29 | DRY_BOREAL(8, OceanSet.COLD), 30 | // temp less than -0.58 31 | SNOWY(9, OceanSet.FROZEN); 32 | 33 | SimplexClimate(int id, OceanSet oceanSet) { 34 | this.id = id; 35 | this.oceanSet = oceanSet; 36 | 37 | SimplexClimateLayer.REVERSE_ID_MAP[id] = this; 38 | } 39 | 40 | public final int id; 41 | public final OceanSet oceanSet; 42 | 43 | public static SimplexClimate fromTemperatureHumidity(double temp, double humidity) { 44 | if (temp < -0.58) { 45 | return SNOWY; 46 | } else if (temp < -0.28) { 47 | if (humidity < -0.3) { 48 | return DRY_BOREAL; 49 | } else if (humidity > 0.3) { 50 | return LUSH_BOREAL; 51 | } else { 52 | return BOREAL; 53 | } 54 | } else if (temp > 0.28) { 55 | if (humidity < -0.3) { 56 | return DRY_TROPICAL; 57 | } else if (humidity > 0.3) { 58 | return LUSH_TROPICAL; 59 | } else { 60 | return TROPICAL; 61 | } 62 | } else { 63 | if (humidity < -0.3) { 64 | return DRY_TEMPERATE; 65 | } else if (humidity > 0.3) { 66 | return LUSH_TEMPERATE; 67 | } else { 68 | return TEMPERATE; 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/biomes/SimplexNether.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api.biomes; 2 | 3 | import net.minecraft.util.Identifier; 4 | import net.minecraft.world.biome.Biome; 5 | import supercoder79.simplexterrain.world.gen.SimplexNetherGeneration; 6 | 7 | /** 8 | * API front for Simplex Terrain's Nether generator. 9 | * 10 | * @author SuperCoder79 11 | */ 12 | public final class SimplexNether { 13 | private SimplexNether() { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/biomes/SquareCrossSamplingLayer.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api.biomes; 2 | 3 | import net.minecraft.world.biome.layer.type.ParentedLayer; 4 | import net.minecraft.world.biome.layer.util.LayerRandomnessSource; 5 | import net.minecraft.world.biome.layer.util.LayerSampleContext; 6 | import net.minecraft.world.biome.layer.util.LayerSampler; 7 | 8 | /** 9 | * Samples all biomes in a 3x3 grid. No, I'm not calling it KingTransformer, what gave you that idea? 10 | * This is probably very bad for performance, so use it sparingly. 11 | * 12 | * @author SuperCoder79 13 | */ 14 | public interface SquareCrossSamplingLayer extends ParentedLayer { 15 | int sampleSquare(LayerRandomnessSource layerRandomnessSource, int w, int nw, int n, int ne, int e, int se, int s, int sw, int center); 16 | 17 | default int sample(LayerSampleContext layerSampleContext, LayerSampler layerSampler, int x, int z) { 18 | return this.sampleSquare(layerSampleContext, 19 | layerSampler.sample(this.transformX(x - 1), this.transformZ(z + 0)), 20 | layerSampler.sample(this.transformX(x - 1), this.transformZ(z + 1)), 21 | layerSampler.sample(this.transformX(x + 0), this.transformZ(z + 1)), 22 | layerSampler.sample(this.transformX(x + 1), this.transformZ(z + 1)), 23 | layerSampler.sample(this.transformX(x + 1), this.transformZ(z + 0)), 24 | layerSampler.sample(this.transformX(x + 1), this.transformZ(z - 1)), 25 | layerSampler.sample(this.transformX(x + 0), this.transformZ(z - 1)), 26 | layerSampler.sample(this.transformX(x - 1), this.transformZ(z - 1)), 27 | layerSampler.sample(this.transformX(x + 0), this.transformZ(z + 0))); 28 | } 29 | 30 | @Override 31 | default int transformX(int i) { 32 | return i; 33 | } 34 | 35 | @Override 36 | default int transformZ(int i) { 37 | return i; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/noise/Noise.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api.noise; 2 | 3 | /** 4 | * A class that can create 2d and 3d noise. 5 | * You *MUST* have at least one constructor in your implementation that takes in only a seed, 6 | * otherwise {@link OctaveNoiseSampler} won't work in conjunction with it. 7 | * 8 | * @author SuperCoder79 9 | */ 10 | public abstract class Noise { 11 | public Noise(long seed) { 12 | } 13 | 14 | public abstract double sample(double x, double z); 15 | 16 | public abstract double sample(double x, double y, double z); 17 | 18 | //Helper noise functions ======================= 19 | 20 | private static final int CHAR_BIT = 8; 21 | private static final int SIZE_INT = 8; 22 | 23 | 24 | /** 25 | * A bit hack that computes a rough estimation of a square root for the given number 26 | * Don't use this in places that need accuracy-- You'll regret it! 27 | * 28 | * @param d the input for the fastSqrt algorithm 29 | * @return a **rough** approximation of square root 30 | */ 31 | public static double fastSqrt(double d) { 32 | return Double.longBitsToDouble(((Double.doubleToLongBits(d) - (1L << 52)) >> 1 ) + (1L << 61)); 33 | } 34 | 35 | /** 36 | * A fast implementation of Math.abs() that avoids branching 37 | * @param n the number to get the absolute value of 38 | * @return the absolute value 39 | */ 40 | public static int fastAbs(int n) { 41 | int mask = n >> (SIZE_INT * CHAR_BIT - 1); 42 | return ((n + mask) ^ mask); 43 | } 44 | 45 | public static long fastAbs(long n) { 46 | long mask = n >> (SIZE_INT * CHAR_BIT - 1); 47 | return ((n + mask) ^ mask); 48 | } 49 | 50 | protected static int factorial(int n) { 51 | if (n == 1) { 52 | return 1; 53 | } else { 54 | return n * factorial(n-1); 55 | } 56 | } 57 | 58 | //ensures that the returned value is in [-1, 1] 59 | protected double clamp(double value) { 60 | return (value > 1) ? 1 : (value < -1) ? -1 : value; 61 | } 62 | 63 | //ensures that the returned value is in [0, 1] 64 | protected double clampPositive(double value) { 65 | return (value < 0) ? 0 : value; 66 | } 67 | 68 | protected static double lerp(double progress, double start, double end) { 69 | return start + progress * (end - start); 70 | } 71 | 72 | protected static double sigmoid(double x) { 73 | return (1/( 1 + Math.exp(-x))); 74 | } 75 | 76 | public static double smoothstep(double d) { 77 | return d * d * d * (d * (d * 6.0 - 15.0) + 10.0); 78 | } 79 | 80 | public static double smootherstep(double t) { 81 | return (1 - t*t)*(1 - t*t); 82 | } 83 | 84 | public static double smootheststep(double t) { 85 | return (1 - t*t)*(1 - t*t)*(1 - t*t); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/noise/NoiseType.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api.noise; 2 | 3 | import supercoder79.simplexterrain.noise.gradient.CubicNoise; 4 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 5 | import supercoder79.simplexterrain.noise.gradient.PerlinNoise; 6 | import supercoder79.simplexterrain.noise.gradient.GaborNoise; 7 | import supercoder79.simplexterrain.noise.value.ValueNoise; 8 | import supercoder79.simplexterrain.noise.voronoi.VoronoiNoise; 9 | import supercoder79.simplexterrain.noise.worley.WorleyNoise; 10 | 11 | public enum NoiseType { 12 | SIMPLEX(OpenSimplexNoise.class), 13 | WORLEY(WorleyNoise.class), 14 | PERLIN(PerlinNoise.class), 15 | VALUE(ValueNoise.class), 16 | CUBIC(CubicNoise.class), 17 | VORONOI(VoronoiNoise.class); 18 | 19 | public final Class noiseClass; 20 | 21 | NoiseType(Class noiseClass) { 22 | this.noiseClass = noiseClass; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/noise/OctaveNoiseSampler.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api.noise; 2 | 3 | import java.lang.reflect.Constructor; 4 | import java.lang.reflect.InvocationTargetException; 5 | import java.util.Random; 6 | 7 | /** 8 | * A helper class used to generify the usage of octaves in noise generation. 9 | * It clamps the values between amplitudeLow and amplitudeHigh 10 | * 11 | * @param The noise sampler that you are using. It must have a constructor with just a long parameter. 12 | * @author Valoeghese and SuperCoder79 13 | */ 14 | public class OctaveNoiseSampler extends Noise { 15 | private Noise[] samplers; 16 | private double clamp; 17 | private double frequency, amplitudeLow, amplitudeHigh; 18 | 19 | private Constructor getNoiseConstructor(Class clazz) { 20 | try { 21 | return clazz.getDeclaredConstructor(long.class); 22 | } catch (NoSuchMethodException e) { 23 | e.printStackTrace(); 24 | } 25 | return null; 26 | } 27 | 28 | /** 29 | * Reflection hackery to make the Noise objects 30 | */ 31 | private T create(Constructor constructor, long seed) { 32 | if (constructor == null) { 33 | return null; 34 | } 35 | 36 | try { 37 | return constructor.newInstance(seed); 38 | } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 39 | e.printStackTrace(); 40 | } 41 | return null; 42 | } 43 | 44 | public OctaveNoiseSampler(Class classT, Random rand, int octaves, double frequency, double amplitudeHigh, double amplitudeLow) { 45 | super(0); 46 | samplers = new Noise[octaves]; 47 | clamp = 1D / (1D - (1D / Math.pow(2, octaves))); 48 | 49 | Constructor constructor = this.getNoiseConstructor(classT); 50 | 51 | for (int i = 0; i < octaves; ++i) { 52 | samplers[i] = create(constructor, rand.nextLong()); 53 | } 54 | 55 | this.frequency = frequency; 56 | this.amplitudeLow = amplitudeLow; 57 | this.amplitudeHigh = amplitudeHigh; 58 | } 59 | 60 | public double sample(double x, double y) { 61 | double amplFreq = 0.5D; 62 | double result = 0; 63 | for (Noise sampler : samplers) { 64 | result += (amplFreq * sampler.sample(x / (amplFreq * frequency), y / (amplFreq * frequency))); 65 | 66 | amplFreq *= 0.5D; 67 | } 68 | 69 | result = result * clamp; 70 | return result > 0 ? result * amplitudeHigh : result * amplitudeLow; 71 | } 72 | 73 | public double sample(double x, double y, double z) { 74 | double amplFreq = 0.5D; 75 | double result = 0; 76 | for (Noise sampler : samplers) { 77 | double freq = amplFreq * frequency; 78 | result += (amplFreq * sampler.sample(x / freq, y / freq, z / freq)); 79 | 80 | amplFreq *= 0.5D; 81 | } 82 | 83 | result = result * clamp; 84 | return result > 0 ? result * amplitudeHigh : result * amplitudeLow; 85 | } 86 | 87 | public double sampleCustom(double x, double y, double freqModifier, double amplitudeHMod, double amplitudeLMod, int octaves) { 88 | double amplFreq = 0.5D; 89 | double result = 0; 90 | 91 | double sampleFreq = frequency * freqModifier; 92 | 93 | for (int i = 0; i < octaves; ++i) { 94 | Noise sampler = samplers[i]; 95 | 96 | double freq = amplFreq * sampleFreq; 97 | result += (amplFreq * sampler.sample(x / freq, y / freq)); 98 | 99 | amplFreq *= 0.5D; 100 | } 101 | 102 | double sampleClamp = 1D / (1D - (1D / Math.pow(2, octaves))); 103 | result *= sampleClamp; 104 | return result > 0 ? result * amplitudeHigh * amplitudeHMod : result * amplitudeLow * amplitudeLMod; 105 | } 106 | 107 | public double sampleCustom(double x, double y, double z, double freqModifier, double amplitudeHMod, double amplitudeLMod, int octaves) { 108 | double amplFreq = 0.5D; 109 | double result = 0; 110 | 111 | double sampleFreq = frequency * freqModifier; 112 | 113 | for (int i = 0; i < octaves; ++i) { 114 | Noise sampler = samplers[i]; 115 | 116 | double freq = amplFreq * sampleFreq; 117 | result += (amplFreq * sampler.sample(x / freq, y / freq, z / freq)); 118 | 119 | amplFreq *= 0.5D; 120 | } 121 | 122 | double sampleClamp = 1D / (1D - (1D / Math.pow(2, octaves))); 123 | result = result * sampleClamp; 124 | return result > 0 ? result * amplitudeHigh * amplitudeHMod : result * amplitudeLow * amplitudeLMod; 125 | } 126 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/noisemodifier/NoiseModifier.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api.noisemodifier; 2 | 3 | import net.minecraft.world.gen.ChunkRandom; 4 | import supercoder79.simplexterrain.api.noise.Noise; 5 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 6 | import supercoder79.simplexterrain.world.BiomeData; 7 | 8 | public interface NoiseModifier { 9 | void init(long seed); 10 | void setup(); 11 | double modify(int x, int z, double currentNoiseValue, BiomeData data); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/postprocess/PostProcessorTarget.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api.postprocess; 2 | 3 | public enum PostProcessorTarget { 4 | NOISE, 5 | CARVERS, 6 | FEATURES 7 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/api/postprocess/TerrainPostProcessor.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.api.postprocess; 2 | 3 | import java.util.Random; 4 | 5 | import net.minecraft.world.WorldAccess; 6 | import supercoder79.simplexterrain.api.Heightmap; 7 | 8 | public interface TerrainPostProcessor { 9 | /** 10 | * This function executes on creation of the chunk generator and is useful for setting up noise functions and randoms. 11 | * 12 | * @param seed the seed used to initialize noise functions and randoms. 13 | */ 14 | void init(long seed); 15 | 16 | /** 17 | * This function executes during setup time, and is useful for configs. 18 | */ 19 | void setup(); 20 | 21 | /** 22 | * This function executes for every chunk being generated. 23 | */ 24 | void process(WorldAccess world, Random rand, int chunkX, int chunkZ, Heightmap heightmap); 25 | 26 | /** 27 | * Returns the specified time for the post processor to be run. 28 | */ 29 | default PostProcessorTarget getTarget() { 30 | return PostProcessorTarget.FEATURES; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/client/GoVote.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.client; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.reflect.TypeToken; 5 | import net.minecraft.client.MinecraftClient; 6 | import net.minecraft.client.gui.screen.ConfirmChatLinkScreen; 7 | import net.minecraft.client.gui.screen.Screen; 8 | import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; 9 | import net.minecraft.client.gui.screen.world.SelectWorldScreen; 10 | import net.minecraft.client.util.math.MatrixStack; 11 | import net.minecraft.text.LiteralText; 12 | import net.minecraft.text.Text; 13 | import net.minecraft.util.Formatting; 14 | import net.minecraft.util.Util; 15 | import org.lwjgl.glfw.GLFW; 16 | 17 | import java.io.IOException; 18 | import java.io.InputStreamReader; 19 | import java.lang.reflect.Type; 20 | import java.net.URL; 21 | import java.net.URLConnection; 22 | import java.nio.charset.StandardCharsets; 23 | import java.nio.file.Files; 24 | import java.nio.file.Path; 25 | import java.nio.file.Paths; 26 | import java.time.LocalDate; 27 | import java.time.Month; 28 | import java.util.*; 29 | 30 | public class GoVote { 31 | private static final String BRAND = "SuperCoder79"; 32 | private static final String MARKER_PATH = ".vote2020_marker"; 33 | private static final LocalDate ELECTION_DAY = LocalDate.of(2020, Month.NOVEMBER, 3); 34 | private static final String LINK = "https://vote.gov/"; 35 | private static boolean shownThisSession = false; 36 | 37 | private static volatile boolean markerAlreadyExists = false; 38 | private static volatile String countryCode = Locale.getDefault().getCountry(); 39 | 40 | public static void init() { 41 | try { 42 | Path path = Paths.get(MARKER_PATH); 43 | Files.createFile(path); 44 | Files.setAttribute(path, "dos:hidden", true); 45 | } catch (IOException ex) { 46 | markerAlreadyExists = true; 47 | return; 48 | } 49 | 50 | if (isAfterElectionDay()) { 51 | return; 52 | } 53 | 54 | new Thread(() -> { 55 | try { 56 | URL url = new URL("http://ip-api.com/json/"); 57 | URLConnection conn = url.openConnection(); 58 | conn.setConnectTimeout(4000); 59 | conn.setReadTimeout(4000); 60 | try (InputStreamReader reader = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)) { 61 | Type typeToken = new TypeToken>() {}.getType(); 62 | Map map = new Gson().fromJson(reader, typeToken); 63 | countryCode = map.get("countryCode"); 64 | } 65 | } catch (IOException ignored) {} 66 | }, "Go Vote Country Check").start(); 67 | } 68 | 69 | private static boolean isAfterElectionDay() { 70 | return LocalDate.now().isAfter(ELECTION_DAY); 71 | } 72 | 73 | public static boolean show(MinecraftClient client, Screen parent) { 74 | if ((parent instanceof SelectWorldScreen || parent instanceof MultiplayerScreen) && shouldShow(client)) { 75 | client.openScreen(new GoVoteScreen(parent)); 76 | shownThisSession = true; 77 | 78 | return true; 79 | } 80 | 81 | return false; 82 | } 83 | 84 | private static boolean shouldShow(MinecraftClient mc) { 85 | if (!isEnglish(mc) || shownThisSession || isAfterElectionDay() || markerAlreadyExists) { 86 | return false; 87 | } 88 | 89 | return "US".equals(countryCode); 90 | } 91 | 92 | private static boolean isEnglish(MinecraftClient mc) { 93 | return mc.getLanguageManager() != null 94 | && mc.getLanguageManager().getLanguage() != null 95 | && "English".equals(mc.getLanguageManager().getLanguage().getName()); 96 | } 97 | 98 | private static class GoVoteScreen extends Screen { 99 | private static final int TICKS_PER_GROUP = 50; 100 | private final Screen parent; 101 | private int ticksElapsed = 0; 102 | private final List> message = new ArrayList<>(); 103 | 104 | protected GoVoteScreen(Screen parent) { 105 | super(new LiteralText("")); 106 | this.parent = parent; 107 | addGroup(s("Please read the following message from " + BRAND + ".")); 108 | addGroup(s("We are at a unique crossroads in the history of our country.")); 109 | addGroup(s("In this time of heightened polarization,"), 110 | s("breakdown of political decorum, and fear,")); 111 | addGroup(s("it is tempting to succumb to apathy,"), 112 | s("to think that nothing you do will matter.")); 113 | addGroup(LiteralText.EMPTY, s("But power is still in the hands of We, the People.")); 114 | addGroup(s("The Constitution and its amendments guarantee every citizen the right to vote.")); 115 | addGroup(s("And it is not only our right, but our ") 116 | .append(s("responsibility").formatted(Formatting.ITALIC, Formatting.GOLD)) 117 | .append(" to do so.")); 118 | addGroup(s("Your vote matters. Always.")); 119 | addGroup(LiteralText.EMPTY, s("Click anywhere to check if you are registered to vote."), 120 | s("The website is an official government site, unaffiliated with " + BRAND + ".")); 121 | addGroup(s("Press ESC to exit. (This screen will not show up again.)")); 122 | addGroup(s("Thank you. - Jasmine \"SuperCoder79\"")); 123 | } 124 | 125 | // Each group appears at the same time 126 | private void addGroup(Text... lines) { 127 | message.add(Arrays.asList(lines)); 128 | } 129 | 130 | private static LiteralText s(String txt) { 131 | return new LiteralText(txt); 132 | } 133 | 134 | @Override 135 | public void tick() { 136 | super.tick(); 137 | ticksElapsed++; 138 | } 139 | 140 | @Override 141 | public void render(MatrixStack mstack, int mx, int my, float pticks) { 142 | super.render(mstack, mx, my, pticks); 143 | 144 | fill(mstack, 0, 0, width, height, 0xFF696969); 145 | int middle = width / 2; 146 | int dist = 12; 147 | 148 | Text note1 = s("Note: If you can't vote in the United States,").formatted(Formatting.ITALIC); 149 | Text note2 = s("Please press ESC and carry on.").formatted(Formatting.ITALIC); 150 | drawCenteredText(mstack, this.textRenderer, note1, middle, 10, 0xFFFFFF); 151 | drawCenteredText(mstack, this.textRenderer, note2, middle, 22, 0xFFFFFF); 152 | 153 | int y = 46; 154 | for (int groupIdx = 0; groupIdx < message.size(); groupIdx++) { 155 | List group = message.get(groupIdx); 156 | if ((ticksElapsed - 20) > groupIdx * TICKS_PER_GROUP) { 157 | for (Text line : group) { 158 | drawCenteredText(mstack, this.textRenderer, line, middle, y, 0xFFFFFF); 159 | y += dist; 160 | } 161 | } 162 | } 163 | } 164 | 165 | @Override 166 | public String getNarrationMessage() { 167 | StringBuilder builder = new StringBuilder(); 168 | for (List group : message) { 169 | for (Text line : group) { 170 | builder.append(line.getString()); 171 | } 172 | } 173 | return builder.toString(); 174 | } 175 | 176 | @Override 177 | public boolean keyPressed(int keycode, int scanCode, int modifiers) { 178 | if (keycode == GLFW.GLFW_KEY_ESCAPE) { 179 | this.client.openScreen(parent); 180 | } 181 | 182 | return super.keyPressed(keycode, scanCode, modifiers); 183 | } 184 | 185 | @Override 186 | public boolean mouseClicked(double x, double y, int modifiers) { 187 | if (ticksElapsed < 80) { 188 | return false; 189 | } 190 | 191 | if (modifiers == 0) { 192 | this.client.openScreen(new ConfirmChatLinkScreen(this::consume, LINK, true)); 193 | return true; 194 | } 195 | 196 | return super.mouseClicked(x, y, modifiers); 197 | } 198 | 199 | private void consume(boolean doIt) { 200 | this.client.openScreen(this); 201 | if (doIt) { 202 | Util.getOperatingSystem().open(LINK); 203 | } 204 | } 205 | 206 | } 207 | 208 | } 209 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/command/MapHeightmapCommand.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.command; 2 | 3 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 4 | import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; 5 | import net.minecraft.server.command.CommandManager; 6 | import net.minecraft.server.command.ServerCommandSource; 7 | import net.minecraft.text.LiteralText; 8 | import supercoder79.simplexterrain.api.Heightmap; 9 | 10 | import javax.imageio.ImageIO; 11 | import java.awt.image.BufferedImage; 12 | import java.io.IOException; 13 | import java.nio.file.Path; 14 | import java.nio.file.Paths; 15 | 16 | public class MapHeightmapCommand { 17 | public static void init() { 18 | CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> { 19 | LiteralArgumentBuilder builder = CommandManager.literal("mapheightmap") 20 | .requires(source -> source.hasPermissionLevel(2)); 21 | 22 | builder.executes(context -> execute(context.getSource())); 23 | 24 | dispatcher.register(builder); 25 | 26 | }); 27 | } 28 | 29 | private static int execute(ServerCommandSource source) { 30 | BufferedImage img = new BufferedImage(2048, 2048, BufferedImage.TYPE_INT_RGB); 31 | 32 | // Unsafe cast but we can hopefully expect people to be safe in dev :P 33 | Heightmap heightmap = (Heightmap) source.getWorld().getChunkManager().getChunkGenerator(); 34 | 35 | for (int x = -1024; x < 1024; x++) { 36 | if (x % 256 == 0) { 37 | source.sendFeedback(new LiteralText(((x + 1024) / 2048.0) * 100 + "%"), false); 38 | } 39 | 40 | for (int z = -1024; z < 1024; z++) { 41 | int height = heightmap.getHeight(x, z); 42 | 43 | img.setRGB(x + 1024, z + 1024, getIntFromColor(height, height, height)); 44 | } 45 | } 46 | 47 | // save the biome map 48 | Path p = Paths.get("heightmap.png"); 49 | try { 50 | ImageIO.write(img, "png", p.toAbsolutePath().toFile()); 51 | } catch (IOException e) { 52 | e.printStackTrace(); 53 | } 54 | 55 | source.sendFeedback(new LiteralText("Mapped heightmap!"), false); 56 | 57 | return 0; 58 | } 59 | 60 | private static int getIntFromColor(int red, int green, int blue) { 61 | red = (red << 16) & 0x00FF0000; //Shift red 16-bits and mask out other stuff 62 | green = (green << 8) & 0x0000FF00; //Shift green 8-bits and mask out other stuff 63 | blue = blue & 0x000000FF; //Mask out anything not blue. 64 | 65 | return 0xFF000000 | red | green | blue; //0xFF000000 for 100% Alpha. Bitwise OR everything together. 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/command/MapNoiseTypeCommand.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.command; 2 | 3 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 4 | import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; 5 | import net.minecraft.command.argument.IdentifierArgumentType; 6 | import net.minecraft.command.suggestion.SuggestionProviders; 7 | import net.minecraft.server.command.CommandManager; 8 | import net.minecraft.server.command.ServerCommandSource; 9 | import net.minecraft.text.LiteralText; 10 | import net.minecraft.util.Identifier; 11 | import net.minecraft.util.registry.Registry; 12 | import net.minecraft.util.registry.RegistryKey; 13 | import net.minecraft.world.biome.Biome; 14 | import supercoder79.simplexterrain.world.noisetype.NoiseType; 15 | import supercoder79.simplexterrain.world.noisetype.NoiseTypeCache; 16 | import supercoder79.simplexterrain.world.noisetype.NoiseTypeHolder; 17 | import supercoder79.simplexterrain.world.noisetype.NoiseTypePicker; 18 | 19 | import javax.imageio.ImageIO; 20 | import java.awt.image.BufferedImage; 21 | import java.io.IOException; 22 | import java.nio.file.Path; 23 | import java.nio.file.Paths; 24 | import java.util.ArrayList; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | public class MapNoiseTypeCommand { 30 | public static void init() { 31 | CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> { 32 | LiteralArgumentBuilder builder = CommandManager.literal("mapnoisetype") 33 | .requires(source -> source.hasPermissionLevel(2)); 34 | 35 | builder.then(CommandManager.argument("biome", IdentifierArgumentType.identifier()).suggests(SuggestionProviders.ALL_BIOMES).executes((commandContext) -> { 36 | return execute(commandContext.getSource(), commandContext.getArgument("biome", Identifier.class)); 37 | })); 38 | 39 | dispatcher.register(builder); 40 | 41 | }); 42 | } 43 | 44 | private static int execute(ServerCommandSource source, Identifier biome) { 45 | Registry biomes = source.getWorld().getRegistryManager().get(Registry.BIOME_KEY); 46 | 47 | RegistryKey key = biomes.getKey(biomes.get(biome)).get(); 48 | 49 | NoiseTypeCache cache = NoiseTypeHolder.get(key); 50 | if (cache != null) { 51 | NoiseTypePicker picker = cache.getPicker(); 52 | List types = new ArrayList<>(picker.getPoints().values()); 53 | Map counts = new HashMap<>(); 54 | 55 | int increment = 255 / types.size(); 56 | int total = 0; 57 | 58 | BufferedImage img = new BufferedImage(2048, 2048, BufferedImage.TYPE_INT_RGB); 59 | 60 | for (int x = -1024; x < 1024; x++) { 61 | if (x % 256 == 0) { 62 | source.sendFeedback(new LiteralText(((x + 1024) / 2048.0) * 100 + "%"), false); 63 | } 64 | 65 | for (int z = -1024; z < 1024; z++) { 66 | NoiseType type = picker.get(x, z); 67 | int color = types.indexOf(type) * increment; 68 | counts.put(type, counts.getOrDefault(type, 0) + 1); 69 | total++; 70 | 71 | img.setRGB(x + 1024, z + 1024, getIntFromColor(color, color, color)); 72 | } 73 | } 74 | 75 | // save the noise type map 76 | Path p = Paths.get("types_" + biome.toString().replace(":", "_") + ".png"); 77 | 78 | for (NoiseType type : types) { 79 | System.out.println(type.getClass().getSimpleName() + " -> " + counts.get(type) + " (" + ((counts.get(type) / (double)total) * 100) + ")%"); 80 | } 81 | 82 | try { 83 | ImageIO.write(img, "png", p.toAbsolutePath().toFile()); 84 | } catch (IOException e) { 85 | e.printStackTrace(); 86 | } 87 | 88 | source.sendFeedback(new LiteralText("Mapped Noise types for " + biome + "!"), false); 89 | 90 | } else { 91 | source.sendError(new LiteralText("This biome does not have a noise type")); 92 | } 93 | 94 | return 1; 95 | } 96 | 97 | private static int getIntFromColor(int red, int green, int blue) { 98 | red = (red << 16) & 0x00FF0000; //Shift red 16-bits and mask out other stuff 99 | green = (green << 8) & 0x0000FF00; //Shift green 8-bits and mask out other stuff 100 | blue = blue & 0x000000FF; //Mask out anything not blue. 101 | 102 | return 0xFF000000 | red | green | blue; //0xFF000000 for 100% Alpha. Bitwise OR everything together. 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/command/ReloadConfigCommand.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.command; 2 | 3 | import com.mojang.brigadier.builder.LiteralArgumentBuilder; 4 | 5 | import net.fabricmc.fabric.api.registry.CommandRegistry; 6 | import net.minecraft.server.command.CommandManager; 7 | import net.minecraft.server.command.ServerCommandSource; 8 | import net.minecraft.text.LiteralText; 9 | import net.minecraft.util.Formatting; 10 | import supercoder79.simplexterrain.configs.ConfigHelper; 11 | 12 | public class ReloadConfigCommand { 13 | public static void init() { 14 | CommandRegistry.INSTANCE.register(false, dispatcher -> { 15 | LiteralArgumentBuilder lab = CommandManager.literal("reloadterrainconfig").requires(executor -> executor.hasPermissionLevel(2)).executes(cmd -> { 16 | ServerCommandSource source = cmd.getSource(); 17 | ConfigHelper.init(); 18 | source.sendFeedback(new LiteralText(Formatting.DARK_GREEN.toString() + Formatting.BOLD.toString() + "Reloaded Configs!"), true); 19 | return 1; 20 | }); 21 | dispatcher.register(lab); 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/compat/VanillaBiomes.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.compat; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import net.minecraft.util.registry.RegistryKey; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.biome.BiomeKeys; 7 | import net.minecraft.world.gen.ChunkRandom; 8 | import supercoder79.simplexterrain.world.noisetype.NoiseTypeCache; 9 | import supercoder79.simplexterrain.world.noisetype.NoiseTypeHolder; 10 | import supercoder79.simplexterrain.world.noisetype.NoiseTypePicker; 11 | import supercoder79.simplexterrain.world.noisetype.desert.DunesNoiseType; 12 | import supercoder79.simplexterrain.world.noisetype.desert.SavannaHillsNoiseType; 13 | import supercoder79.simplexterrain.world.noisetype.forest.HillsNoiseType; 14 | import supercoder79.simplexterrain.world.noisetype.plains.LowLyingPlainsNoiseType; 15 | import supercoder79.simplexterrain.world.noisetype.plains.ForestedHillsNoiseType; 16 | import supercoder79.simplexterrain.world.noisetype.plains.MountainsNoiseType; 17 | import supercoder79.simplexterrain.world.noisetype.plains.PlainsNoiseType; 18 | 19 | import java.util.function.Function; 20 | 21 | public class VanillaBiomes { 22 | public static void register() { 23 | register(BiomeKeys.PLAINS, VanillaBiomes::createPlains); 24 | register(BiomeKeys.FOREST, VanillaBiomes::createForest); 25 | register(BiomeKeys.DESERT, VanillaBiomes::createDesert); 26 | } 27 | 28 | private static void register(RegistryKey key, Function factory) { 29 | NoiseTypeHolder.BIOME_FACTORIES.put(key, factory); 30 | } 31 | 32 | private static NoiseTypeCache createPlains(ChunkRandom random) { 33 | PlainsNoiseType plains = new PlainsNoiseType(); 34 | plains.init(random); 35 | 36 | ForestedHillsNoiseType hills = new ForestedHillsNoiseType(); 37 | hills.init(random); 38 | 39 | MountainsNoiseType mountains = new MountainsNoiseType(); 40 | mountains.init(random); 41 | 42 | LowLyingPlainsNoiseType lakes = new LowLyingPlainsNoiseType(); 43 | lakes.init(random); 44 | 45 | NoiseTypePicker picker = new NoiseTypePicker(random, ImmutableList.of(plains, hills, lakes, mountains)); 46 | return new NoiseTypeCache(picker); 47 | } 48 | 49 | private static NoiseTypeCache createForest(ChunkRandom random) { 50 | PlainsNoiseType plains = new PlainsNoiseType(); 51 | plains.init(random); 52 | 53 | HillsNoiseType hills = new HillsNoiseType(); 54 | hills.init(random); 55 | 56 | NoiseTypePicker picker = new NoiseTypePicker(random, ImmutableList.of(plains, hills)); 57 | return new NoiseTypeCache(picker); 58 | } 59 | 60 | private static NoiseTypeCache createDesert(ChunkRandom random) { 61 | HillsNoiseType hills = new HillsNoiseType(); 62 | hills.init(random); 63 | 64 | DunesNoiseType dunes = new DunesNoiseType(); 65 | dunes.init(random); 66 | 67 | SavannaHillsNoiseType savanna = new SavannaHillsNoiseType(); 68 | savanna.init(random); 69 | 70 | NoiseTypePicker picker = new NoiseTypePicker(random, ImmutableList.of(dunes, hills, savanna)); 71 | return new NoiseTypeCache(picker); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/ConfigHelper.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.FileReader; 5 | import java.io.FileWriter; 6 | import java.io.IOException; 7 | import java.lang.reflect.Constructor; 8 | import java.lang.reflect.InvocationTargetException; 9 | import java.nio.file.Files; 10 | import java.nio.file.Path; 11 | import java.nio.file.Paths; 12 | 13 | import com.google.gson.Gson; 14 | import com.google.gson.GsonBuilder; 15 | 16 | import supercoder79.simplexterrain.SimplexTerrain; 17 | import supercoder79.simplexterrain.api.noise.NoiseType; 18 | 19 | public class ConfigHelper { 20 | public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); 21 | 22 | private static Constructor getConstructor(Class clazz) { 23 | try { 24 | return clazz.getDeclaredConstructor(); 25 | } catch (NoSuchMethodException e) { 26 | e.printStackTrace(); 27 | } 28 | return null; 29 | } 30 | 31 | private static T create(Constructor constructor) { 32 | if (constructor == null) { 33 | return null; 34 | } 35 | 36 | try { 37 | return constructor.newInstance(); 38 | } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 39 | e.printStackTrace(); 40 | } 41 | return null; 42 | } 43 | 44 | public static T getFromConfig(Class configClass, Path path) { 45 | T config = create(getConstructor(configClass)); 46 | try { 47 | //config exists: return value 48 | if (Files.exists(path)) { 49 | config = GSON.fromJson(new FileReader(path.toFile()), configClass); 50 | 51 | //update to newest config using le epic reflection hacks 52 | String version = (String) config.getClass().getField("version").get(config); 53 | if (!version.equals(SimplexTerrain.VERSION)) { 54 | config.getClass().getField("version").set(config, SimplexTerrain.VERSION); 55 | BufferedWriter writer = new BufferedWriter(new FileWriter(path.toFile())); 56 | writer.write(GSON.toJson(config)); 57 | writer.close(); 58 | } 59 | } else { 60 | //config does not exist: write value 61 | BufferedWriter writer = new BufferedWriter(new FileWriter(path.toFile())); 62 | writer.write(GSON.toJson(config)); 63 | writer.close(); 64 | } 65 | } catch (IOException | NoSuchFieldException | IllegalAccessException e) { 66 | e.printStackTrace(); 67 | } 68 | return config; 69 | } 70 | 71 | public static void init() { 72 | MainConfigData configData = null; 73 | try { 74 | 75 | Path configDir = Paths.get("", "config", "simplexterrain.json"); 76 | if (Files.exists(configDir)) { 77 | configData = GSON.fromJson(new FileReader(configDir.toFile()), MainConfigData.class); 78 | //save new values 79 | if (!configData.configVersion.equals(SimplexTerrain.VERSION)) { 80 | configData.configVersion = SimplexTerrain.VERSION; 81 | BufferedWriter writer = new BufferedWriter(new FileWriter(configDir.toFile())); 82 | writer.write(GSON.toJson(configData)); 83 | writer.close(); 84 | } 85 | } else { 86 | configData = new MainConfigData(); 87 | Paths.get("", "config").toFile().mkdirs(); 88 | BufferedWriter writer = new BufferedWriter(new FileWriter(configDir.toFile())); 89 | writer.write(GSON.toJson(configData)); 90 | 91 | writer.close(); 92 | } 93 | } catch (IOException e) { 94 | e.printStackTrace(); 95 | } 96 | if (configData.noiseGenerator == null) { 97 | System.out.println("[Simplex Terrain] The noise generator was null! Falling back to Simplex!"); 98 | configData.noiseGenerator = NoiseType.SIMPLEX; 99 | } 100 | 101 | SimplexTerrain.CONFIG = configData; 102 | 103 | Paths.get("", "config", "simplexterrain", "noisemodifiers").toFile().mkdirs(); 104 | Paths.get("", "config", "simplexterrain", "postprocessors").toFile().mkdirs(); 105 | 106 | // Setup (reading from configs and stuff like that) 107 | SimplexTerrain.CONFIG.postProcessors.forEach(postProcessors -> postProcessors.postProcessor.setup()); 108 | SimplexTerrain.CONFIG.noiseModifiers.forEach(noiseModifiers -> noiseModifiers.noiseModifier.setup()); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/MainConfigData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | import com.google.gson.annotations.SerializedName; 8 | 9 | import supercoder79.simplexterrain.SimplexTerrain; 10 | import supercoder79.simplexterrain.api.noise.NoiseType; 11 | import supercoder79.simplexterrain.world.noisemodifier.NoiseModifiers; 12 | import supercoder79.simplexterrain.world.postprocessor.PostProcessors; 13 | 14 | public class MainConfigData { 15 | public String configVersion = SimplexTerrain.VERSION; 16 | public boolean doModCompat = true; 17 | public boolean reloadConfigCommand = false; 18 | public boolean threadedNoiseGeneration = true; 19 | public boolean deleteLakes = false; 20 | public boolean generateVanillaCaves = true; 21 | public boolean simplexNetherGeneration = true; 22 | 23 | public int noiseGenerationThreads = 2; 24 | 25 | public NoiseType noiseGenerator = NoiseType.SIMPLEX; 26 | 27 | public List postProcessors = new ArrayList<>(); 28 | 29 | public List noiseModifiers = Arrays.asList(NoiseModifiers.MOUNTAINS, NoiseModifiers.RIDGES, NoiseModifiers.DETAILS, NoiseModifiers.RIVERS, NoiseModifiers.MUSHROOM_ISLANDS); 30 | 31 | public int mainOctaveAmount = 3; 32 | public double mainFrequency = 3200.0; 33 | public double mainAmplitudeHigh = 144.0; 34 | public double mainAmplitudeLow = 32.0; 35 | public double mainNetherScale = 70.0; 36 | public double netherThresholdScale = 28.0; 37 | public double netherThresholdAmplitude = 0.125; 38 | public double netherThresholdBase = 0.25; 39 | 40 | public int lowlandStartHeight = 66; 41 | public int midlandStartHeight = 90; 42 | public int highlandStartHeight = 140; 43 | public int toplandStartHeight = 190; 44 | 45 | public int biomeScaleAmount = 8; 46 | 47 | public double temperatureOffset = 0.0; 48 | public double humidityOffset = 0.0; 49 | 50 | public int seaLevel = 63; 51 | 52 | public int temperatureOctaveAmount = 1; 53 | public int humidityOctaveAmount = 2; 54 | public double temperatureFrequency = 15.0; 55 | public double humidityFrequency = 11.0; 56 | public double temperatureAmplitude = 1.2; 57 | public double humidityAmplitude = 1.2; 58 | 59 | public double cloudHeight = 192; 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/noisemodifiers/DetailsConfigData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs.noisemodifiers; 2 | 3 | import supercoder79.simplexterrain.SimplexTerrain; 4 | 5 | public class DetailsConfigData { 6 | public String version = SimplexTerrain.VERSION; 7 | public int octaves = 3; 8 | public double frequency = 32; 9 | public double amplitudeHigh = 2; 10 | public double amplitudeLow = 2; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/noisemodifiers/MountainConfigData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs.noisemodifiers; 2 | 3 | import supercoder79.simplexterrain.SimplexTerrain; 4 | 5 | public class MountainConfigData { 6 | public String version = SimplexTerrain.VERSION; 7 | public int octaves = 3; 8 | public double frequency = 2800; 9 | public double amplitudeHigh = 256; 10 | public double amplitudeLow = 64; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/noisemodifiers/MushroomFieldsConfigData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs.noisemodifiers; 2 | 3 | import supercoder79.simplexterrain.SimplexTerrain; 4 | 5 | public class MushroomFieldsConfigData { 6 | public String version = SimplexTerrain.VERSION; 7 | public double scale = 980.0; 8 | public double threshold = 0.82; 9 | public double height = 44.0; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/noisemodifiers/PlateausConfigData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs.noisemodifiers; 2 | 3 | import supercoder79.simplexterrain.SimplexTerrain; 4 | 5 | public class PlateausConfigData { 6 | public String version = SimplexTerrain.VERSION; 7 | public int octaves = 2; 8 | public double frequency = 320; 9 | public double threshold = 0.4; 10 | public double interpolation = 0.045; 11 | public double height = 12.0; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/noisemodifiers/RidgesConfigData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs.noisemodifiers; 2 | 3 | import supercoder79.simplexterrain.SimplexTerrain; 4 | 5 | public class RidgesConfigData { 6 | public String version = SimplexTerrain.VERSION; 7 | public int octaves = 3; 8 | public double frequency = 768; 9 | public double amplitude = 80; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/noisemodifiers/RiversConfigData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs.noisemodifiers; 2 | 3 | import supercoder79.simplexterrain.SimplexTerrain; 4 | 5 | public class RiversConfigData { 6 | public String version = SimplexTerrain.VERSION; 7 | public double scale = 980.0; 8 | public double size = 0.12; 9 | public double depth = 72; // TODO: reverse sigmoid 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/postprocessors/CaveConfigData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs.postprocessors; 2 | 3 | import supercoder79.simplexterrain.SimplexTerrain; 4 | 5 | public class CaveConfigData { 6 | public String version = SimplexTerrain.VERSION; 7 | public int caveNoiseOctaves = 6; 8 | public int caveHeightOctaves = 5; 9 | public int caveEnabledOctaves = 2; 10 | 11 | public double caveNoiseFrequency = 2048.0; 12 | public double caveHeightFrequency = 32.0; 13 | public double caveEnabledFrequency = 1024.0; 14 | 15 | public double caveNoiseAmplitudeHigh = 14.0; 16 | public double caveNoiseAmplitudeLow = 14.0; 17 | 18 | public double caveHeightAmplitudeHigh = 10.0; 19 | public double caveHeightAmplitudeLow = 10.0; 20 | 21 | public double caveEnabledAmplitudeHigh = 1.0; 22 | public double caveEnabledAmplitudeLow = 1.0; 23 | 24 | public double caveEnabledThreshold = 0.0; 25 | public int baseHeight = 30; 26 | 27 | public int caveDeletionThreshold = 3; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/postprocessors/ErosionConfigData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs.postprocessors; 2 | 3 | import supercoder79.simplexterrain.SimplexTerrain; 4 | 5 | public class ErosionConfigData { 6 | public String version = SimplexTerrain.VERSION; 7 | public int octaves = 4; 8 | public double frequency = 128.0; 9 | public double amplitudeHigh = 6.0; 10 | public double amplitudeLow = 8.0; 11 | 12 | public double baseNoise = 0.1; 13 | public double threshold = 0.0; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/postprocessors/RiverConfigData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs.postprocessors; 2 | 3 | import supercoder79.simplexterrain.SimplexTerrain; 4 | 5 | public class RiverConfigData { 6 | public String version = SimplexTerrain.VERSION; 7 | public String comment = "NOTE: This post processor will get an overhaul in a future update"; 8 | public int sandNoiseOctaves = 4; 9 | public double sandNoiseFrequency = 4096.0; 10 | public double sandNoiseAmplitudeHigh = 2.0; 11 | public double sandNoiseAmplitudeLow = 2.0; 12 | 13 | public double scale = 980; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/configs/postprocessors/SoilConfigData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.configs.postprocessors; 2 | 3 | import supercoder79.simplexterrain.SimplexTerrain; 4 | 5 | public class SoilConfigData { 6 | public String version = SimplexTerrain.VERSION; 7 | public int coarseDirtOctaves = 4; 8 | public double coarseDirtFrequency = 256.0; 9 | public double coarseDirtAmplitudeHigh = 6.0; 10 | public double coarseDirtAmplitudeLow = 8.0; 11 | 12 | public int podzolOctaves = 4; 13 | public double podzolFrequency = 256.0; 14 | public double podzolAmplitudeHigh = 6.0; 15 | public double podzolAmplitudeLow = 8.0; 16 | 17 | public double coarseDirtThreshold = 0.65; 18 | public double podzolThreshold = -0.65; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/mixin/MixinChunkStatus.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.mixin; 2 | 3 | import net.minecraft.server.world.ServerWorld; 4 | import net.minecraft.world.ChunkRegion; 5 | import net.minecraft.world.chunk.Chunk; 6 | import net.minecraft.world.chunk.ChunkStatus; 7 | import net.minecraft.world.gen.chunk.ChunkGenerator; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 12 | import supercoder79.simplexterrain.world.gen.SimplexChunkGenerator; 13 | 14 | import java.util.List; 15 | 16 | @SuppressWarnings("UnresolvedMixinReference") //synthetic lambda method 17 | @Mixin(ChunkStatus.class) 18 | public class MixinChunkStatus { 19 | 20 | @Inject(method = "method_16563", at = @At("HEAD"), remap = false) 21 | private static void carveSanely(ServerWorld world, ChunkGenerator generator, List list, Chunk chunk, CallbackInfo info) { 22 | if (generator instanceof SimplexChunkGenerator) { 23 | ((SimplexChunkGenerator)generator).carvePostProcessors(new ChunkRegion(world, list), chunk); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/mixin/MixinGeneratorOptions.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.mixin; 2 | 3 | import com.google.common.base.MoreObjects; 4 | import net.minecraft.util.registry.DynamicRegistryManager; 5 | import net.minecraft.util.registry.Registry; 6 | import net.minecraft.util.registry.SimpleRegistry; 7 | import net.minecraft.world.biome.Biome; 8 | import net.minecraft.world.dimension.DimensionOptions; 9 | import net.minecraft.world.dimension.DimensionType; 10 | import net.minecraft.world.gen.GeneratorOptions; 11 | import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.injection.At; 14 | import org.spongepowered.asm.mixin.injection.Inject; 15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 16 | import supercoder79.simplexterrain.configs.ConfigHelper; 17 | import supercoder79.simplexterrain.world.gen.SimplexBiomeSource; 18 | import supercoder79.simplexterrain.world.gen.SimplexChunkGenerator; 19 | 20 | import java.util.Properties; 21 | import java.util.Random; 22 | 23 | @Mixin(GeneratorOptions.class) 24 | public class MixinGeneratorOptions { 25 | @Inject(method = "fromProperties", at = @At("HEAD"), cancellable = true) 26 | private static void injectSimplex(DynamicRegistryManager dynamicRegistryManager, Properties properties, CallbackInfoReturnable cir) { 27 | if (properties.get("level-type") == null) { 28 | return; 29 | } 30 | 31 | if (properties.get("level-type").toString().trim().toLowerCase().equals("simplex")) { 32 | ConfigHelper.init(); 33 | String seed = (String) MoreObjects.firstNonNull(properties.get("level-seed"), ""); 34 | long l = new Random().nextLong(); 35 | if (!seed.isEmpty()) { 36 | try { 37 | long m = Long.parseLong(seed); 38 | if (m != 0L) { 39 | l = m; 40 | } 41 | } catch (NumberFormatException exception) { 42 | l = seed.hashCode(); 43 | } 44 | } 45 | 46 | String generate_structures = (String)properties.get("generate-structures"); 47 | boolean generateStructures = generate_structures == null || Boolean.parseBoolean(generate_structures); 48 | Registry dimensionTypes = dynamicRegistryManager.get(Registry.DIMENSION_TYPE_KEY); 49 | Registry biomes = dynamicRegistryManager.get(Registry.BIOME_KEY); 50 | Registry chunkGeneratorSettings = dynamicRegistryManager.get(Registry.NOISE_SETTINGS_WORLDGEN); 51 | SimpleRegistry dimensionOptions = DimensionType.createDefaultDimensionOptions(dimensionTypes, biomes, chunkGeneratorSettings, l); 52 | cir.setReturnValue(new GeneratorOptions(l, generateStructures, false, GeneratorOptions.method_28608(dimensionTypes, dimensionOptions, new SimplexChunkGenerator(new SimplexBiomeSource(biomes, l), l)))); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/mixin/MixinMinecraftServer.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.mixin; 2 | 3 | import com.mojang.authlib.GameProfileRepository; 4 | import com.mojang.authlib.minecraft.MinecraftSessionService; 5 | import com.mojang.datafixers.DataFixer; 6 | import net.minecraft.resource.ResourcePackManager; 7 | import net.minecraft.resource.ServerResourceManager; 8 | import net.minecraft.server.MinecraftServer; 9 | import net.minecraft.server.WorldGenerationProgressListenerFactory; 10 | import net.minecraft.util.UserCache; 11 | import net.minecraft.util.math.BlockPos; 12 | import net.minecraft.util.registry.DynamicRegistryManager; 13 | import net.minecraft.world.SaveProperties; 14 | import net.minecraft.world.biome.Biome; 15 | import net.minecraft.world.biome.source.BiomeSource; 16 | import net.minecraft.world.level.storage.LevelStorage; 17 | import org.spongepowered.asm.mixin.Mixin; 18 | import org.spongepowered.asm.mixin.injection.At; 19 | import org.spongepowered.asm.mixin.injection.Inject; 20 | import org.spongepowered.asm.mixin.injection.Redirect; 21 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 22 | import supercoder79.simplexterrain.SimplexTerrain; 23 | import supercoder79.simplexterrain.world.gen.SimplexChunkGenerator; 24 | 25 | import java.net.Proxy; 26 | import java.util.Random; 27 | import java.util.function.Predicate; 28 | 29 | @Mixin(MinecraftServer.class) 30 | public class MixinMinecraftServer { 31 | @Inject(method = "", at = @At("RETURN")) 32 | private void hookConstructor(Thread thread, DynamicRegistryManager.Impl impl, LevelStorage.Session session, SaveProperties saveProperties, ResourcePackManager resourcePackManager, Proxy proxy, DataFixer dataFixer, ServerResourceManager serverResourceManager, MinecraftSessionService minecraftSessionService, GameProfileRepository gameProfileRepository, UserCache userCache, WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, CallbackInfo ci) { 33 | if (saveProperties.getGeneratorOptions().getChunkGenerator() instanceof SimplexChunkGenerator) { 34 | SimplexTerrain.isSimplexEnabled = true; 35 | } else { 36 | SimplexTerrain.isSimplexEnabled = false; 37 | } 38 | } 39 | 40 | @Redirect(method = "setupSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/biome/source/BiomeSource;locateBiome(IIIILjava/util/function/Predicate;Ljava/util/Random;)Lnet/minecraft/util/math/BlockPos;")) 41 | private static BlockPos fixDumbServerCrash(BiomeSource biomeSource, int x, int y, int z, int radius, Predicate target, Random random) { 42 | //TODO: unfuck this code 43 | try { 44 | return biomeSource.locateBiome(x, y, z, radius, target, random); 45 | } catch (Exception e) { 46 | System.out.println("[Simplex Terrain] If your server stalls here i'm really sorry but you're gonna have to kill it and restart it."); 47 | System.out.println("[Simplex Terrain] I have no clue why this happens but it does."); 48 | System.out.println("[Simplex Terrain] I'll try to get it fixed, but for now this is the workaround - SuperCoder79"); 49 | return new BlockPos(0, 63, 0); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/mixin/MixinNoiseChunkGenerator.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.mixin; 2 | 3 | import net.minecraft.util.registry.Registry; 4 | import net.minecraft.world.ChunkRegion; 5 | import net.minecraft.world.WorldAccess; 6 | import net.minecraft.world.biome.Biome; 7 | import net.minecraft.world.biome.source.BiomeSource; 8 | import net.minecraft.world.chunk.Chunk; 9 | import net.minecraft.world.dimension.DimensionType; 10 | import net.minecraft.world.gen.StructureAccessor; 11 | import net.minecraft.world.gen.chunk.*; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.injection.At; 14 | import org.spongepowered.asm.mixin.injection.Inject; 15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 16 | import supercoder79.simplexterrain.SimplexTerrain; 17 | import supercoder79.simplexterrain.world.gen.SimplexNetherGeneration; 18 | 19 | import java.util.function.Supplier; 20 | 21 | @Mixin(NoiseChunkGenerator.class) 22 | public abstract class MixinNoiseChunkGenerator extends ChunkGenerator { 23 | 24 | public MixinNoiseChunkGenerator(BiomeSource biomeSource, StructuresConfig config) { 25 | super(biomeSource, config); 26 | } 27 | 28 | @Inject(method = "(Lnet/minecraft/world/biome/source/BiomeSource;Lnet/minecraft/world/biome/source/BiomeSource;JLjava/util/function/Supplier;)V", at = @At("RETURN")) 29 | private void constructor(BiomeSource biomeSource, BiomeSource biomeSource2, long worldSeed, Supplier supplier, CallbackInfo ci) { 30 | SimplexNetherGeneration.init(worldSeed); 31 | } 32 | 33 | @Inject(method = "populateNoise", at = @At("HEAD"), cancellable = true) 34 | public void populateNoise(WorldAccess world, StructureAccessor accessor, Chunk chunk, CallbackInfo ci) { 35 | Registry dimensions = ((ChunkRegion)world).toServerWorld().getRegistryManager().get(Registry.DIMENSION_TYPE_KEY); 36 | 37 | // replace the nether with ours if we're in a simplex terrain world and nether generation is enabled 38 | if (SimplexTerrain.isSimplexEnabled && dimensions.getId(world.getDimension()) == DimensionType.THE_NETHER_REGISTRY_KEY.getValue() && SimplexTerrain.CONFIG.simplexNetherGeneration) { 39 | SimplexNetherGeneration.generate(world, chunk, this.biomeSource, getSeaLevel()); 40 | ci.cancel(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/mixin/MixinSpawnLocating.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.mixin; 2 | 3 | import net.minecraft.server.network.SpawnLocating; 4 | import net.minecraft.server.world.ServerWorld; 5 | import net.minecraft.util.math.BlockPos; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.Shadow; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Redirect; 10 | 11 | @Mixin(SpawnLocating.class) 12 | public abstract class MixinSpawnLocating { 13 | 14 | @Shadow 15 | protected static BlockPos findOverworldSpawn(ServerWorld world, int x, int z, boolean validSpawnNeeded) { 16 | return null; 17 | } 18 | 19 | @Redirect(method = "findServerSpawnPoint", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/SpawnLocating;findOverworldSpawn(Lnet/minecraft/server/world/ServerWorld;IIZ)Lnet/minecraft/util/math/BlockPos;")) 20 | private static BlockPos getPos(ServerWorld world, int x, int z, boolean validSpawnNeeded) { 21 | try { 22 | return findOverworldSpawn(world, x, z, validSpawnNeeded); 23 | } catch (Exception e) { 24 | return new BlockPos(x + 8, world.getSeaLevel(), z + 8); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/mixin/antibad/MixinLakeFeature.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.mixin.antibad; 2 | 3 | import net.minecraft.util.math.BlockPos; 4 | import net.minecraft.world.ServerWorldAccess; 5 | import net.minecraft.world.StructureWorldAccess; 6 | import net.minecraft.world.gen.StructureAccessor; 7 | import net.minecraft.world.gen.chunk.ChunkGenerator; 8 | import net.minecraft.world.gen.feature.LakeFeature; 9 | import net.minecraft.world.gen.feature.SingleStateFeatureConfig; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 14 | import supercoder79.simplexterrain.SimplexTerrain; 15 | 16 | import java.util.Random; 17 | 18 | @Mixin(LakeFeature.class) 19 | public class MixinLakeFeature { 20 | @Inject(method = "generate", at = @At("HEAD"), cancellable = true) 21 | public void noLakesPls(StructureWorldAccess structureWorldAccess, ChunkGenerator chunkGenerator, Random random, BlockPos blockPos, SingleStateFeatureConfig singleStateFeatureConfig, CallbackInfoReturnable cir) { 22 | if (SimplexTerrain.CONFIG.deleteLakes && SimplexTerrain.isSimplexEnabled) cir.setReturnValue(false); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/mixin/client/MixinMinecraftClient.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.mixin.client; 2 | 3 | import net.minecraft.client.MinecraftClient; 4 | import net.minecraft.client.gui.screen.Screen; 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 | import supercoder79.simplexterrain.client.GoVote; 10 | 11 | @Mixin(MinecraftClient.class) 12 | public class MixinMinecraftClient { 13 | 14 | @Inject(method = "openScreen", at = @At("HEAD"), cancellable = true) 15 | private void handleVoteScreen(Screen screen, CallbackInfo ci) { 16 | // Handle the go vote screen. Go vote. Please. 17 | if (GoVote.show((MinecraftClient)(Object)this, screen)) { 18 | ci.cancel(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/mixin/client/MixinSkyProperties.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.mixin.client; 2 | 3 | import net.fabricmc.api.EnvType; 4 | import net.fabricmc.api.Environment; 5 | import net.minecraft.client.MinecraftClient; 6 | import net.minecraft.client.render.SkyProperties; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Inject; 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 11 | import supercoder79.simplexterrain.SimplexTerrain; 12 | 13 | @Environment(EnvType.CLIENT) 14 | @Mixin(SkyProperties.class) 15 | public class MixinSkyProperties { 16 | @Inject(method = "getCloudsHeight", at = @At("HEAD"), cancellable = true) 17 | private void getCloudsHeight(CallbackInfoReturnable info) { 18 | 19 | // I don't feel like making simplex terrain send over multiplayer data, so.... for now this is hardcoded to singleplayer 20 | if (SimplexTerrain.isSimplexEnabled && MinecraftClient.getInstance().isInSingleplayer()) { 21 | info.setReturnValue((float) SimplexTerrain.CONFIG.cloudHeight); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/mixin/optichunk/MixinChunkSection.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.mixin.optichunk; 2 | 3 | import org.spongepowered.asm.mixin.Final; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Shadow; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.Redirect; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 10 | 11 | import net.minecraft.block.BlockState; 12 | import net.minecraft.world.chunk.ChunkSection; 13 | import net.minecraft.world.chunk.PalettedContainer; 14 | import supercoder79.simplexterrain.SimplexTerrain; 15 | 16 | @Mixin(ChunkSection.class) 17 | public class MixinChunkSection { 18 | 19 | @SuppressWarnings("unchecked") 20 | @Redirect(method = "setBlockState(IIILnet/minecraft/block/BlockState;Z)Lnet/minecraft/block/BlockState;", 21 | at = @At(target = "Lnet/minecraft/world/chunk/PalettedContainer;setSync(IIILjava/lang/Object;)Ljava/lang/Object;", value = "INVOKE")) 22 | private Object noLock(PalettedContainer container, int x, int y, int z, Object value) { 23 | return container.set(x, y, z, value); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/noise/NoiseMath.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.noise; 2 | 3 | import supercoder79.simplexterrain.api.noise.Noise; 4 | 5 | public class NoiseMath { 6 | private static final double CONST = 0.1; 7 | 8 | // Derivative code 9 | 10 | public static double derivative(Noise sampler, double x, double z) { 11 | double baseSample = sigmoid(sampler.sample(x, z)); 12 | 13 | double xVal1 = sigmoid(sampler.sample(x + CONST, z) - baseSample) / CONST; 14 | double xVal2 = sigmoid(sampler.sample(x - CONST, z) - baseSample) / CONST; 15 | double zVal1 = sigmoid(sampler.sample(x, z + CONST) - baseSample) / CONST; 16 | double zVal2 = sigmoid(sampler.sample(x, z - CONST) - baseSample) / CONST; 17 | 18 | return Math.sqrt(((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1))); 19 | } 20 | 21 | public static double derivative2(Noise sampler, double x, double z) { 22 | double a = 0.788675134594813 * CONST; 23 | double b = 0.211324865405187 * CONST; 24 | double c = 0.577350269189626 * CONST; 25 | 26 | double v1 = sigmoid(sampler.sample(x + a, z - b)); 27 | double v2 = sigmoid(sampler.sample(x - b, z + a)); 28 | double v3 = sigmoid(sampler.sample(x - c, z - c)); 29 | 30 | double dx = (v1 * a + v2 * -b + v3 * -c) * (0.40824829046386296 / CONST); 31 | double dy = (v1 * -b + v2 * a + v3 * -c) * (0.40824829046386296 / CONST); 32 | 33 | return Math.sqrt(dx*dx + dy*dy); 34 | } 35 | 36 | public static double derivative(Noise sampler, double x, double y, double z) { 37 | double baseSample = sigmoid(sampler.sample(x, y, z)); 38 | 39 | double xVal1 = sigmoid(sampler.sample(x + CONST, y, z) - baseSample) / CONST; 40 | double xVal2 = sigmoid(sampler.sample(x - CONST, y, z) - baseSample) / CONST; 41 | double zVal1 = sigmoid(sampler.sample(x, y, z + CONST) - baseSample) / CONST; 42 | double zVal2 = sigmoid(sampler.sample(x, y, z - CONST) - baseSample) / CONST; 43 | double yVal1 = sigmoid(sampler.sample(x, y + CONST, z) - baseSample) / CONST; 44 | double yVal2 = sigmoid(sampler.sample(x, y - CONST, z) - baseSample) / CONST; 45 | 46 | return Math.sqrt(((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1)) + ((yVal2 - yVal1) * (yVal2 - yVal1))); 47 | } 48 | 49 | //Utilities 50 | 51 | // \frac{256}{e^{\frac{7}{3}-\frac{x}{64}}+1} 52 | public static double sigmoid(double val) { 53 | return 256 / (Math.exp(7 / 3f - val / 64) + 1); 54 | } 55 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/noise/gradient/CubicNoise.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.noise.gradient; 2 | 3 | import supercoder79.simplexterrain.api.noise.Noise; 4 | 5 | public class CubicNoise extends Noise { 6 | private static final int RND_A = 134775813; 7 | private static final int RND_B = 1103515245; 8 | 9 | private long seed; 10 | private int octave; 11 | private int periodx = (int)Math.pow(2, 10); 12 | private int periody = (int)Math.pow(2, 10); 13 | 14 | // public CubicNoise(final int seed, final int octave, final int periodx, final int periody) { 15 | // this(seed); 16 | // 17 | // this.periodx = periodx; 18 | // this.periody = periody; 19 | // } 20 | 21 | public CubicNoise(long seed) { 22 | super(seed); 23 | this.seed = seed; 24 | this.octave = 1; 25 | } 26 | 27 | public double sample(final double x) { 28 | final int xi = (int) Math.floor(x / octave); 29 | final double lerp = x / octave - xi; 30 | 31 | return interpolate( 32 | randomize(seed, tile(xi - 1, periodx), 0), 33 | randomize(seed, tile(xi, periodx), 0), 34 | randomize(seed, tile(xi + 1, periodx), 0), 35 | randomize(seed, tile(xi + 2, periodx), 0), 36 | lerp) * 0.5f + 0.25f; 37 | } 38 | 39 | public double sample(double x, double y) { 40 | x *= 0.5; 41 | y *= 0.5; 42 | final int xi = (int) Math.floor(x / octave); 43 | final double lerpx = x / octave - xi; 44 | final int yi = (int) Math.floor(y / octave); 45 | final double lerpy = y / octave - yi; 46 | 47 | double[] xSamples = new double[4]; 48 | 49 | for(int i = 0; i < 4; ++i) 50 | xSamples[i] = interpolate( 51 | randomize(seed, tile(xi - 1, periodx), tile(yi - 1 + i, periody)), 52 | randomize(seed, tile(xi, periodx), tile(yi - 1 + i, periody)), 53 | randomize(seed, tile(xi + 1, periodx), tile(yi - 1 + i, periody)), 54 | randomize(seed, tile(xi + 2, periodx), tile(yi - 1 + i, periody)), 55 | lerpx); 56 | double d = (interpolate(xSamples[0], xSamples[1], xSamples[2], xSamples[3], lerpy) * 0.125f + 0.25f); 57 | d /= Math.pow(10, 9) / 2; 58 | return d; 59 | } 60 | 61 | @Override 62 | public double sample(double x, double y, double z) { 63 | return 0; 64 | } 65 | 66 | private static double randomize(final long seed, final int x, final int y) { 67 | return (float) ((((x ^ y) * RND_A) ^ (seed + x)) * (((RND_B * x) << 16) ^ (RND_B * y) - RND_A)) / Integer.MAX_VALUE; 68 | } 69 | 70 | private static int tile(final int coordinate, final int period) { 71 | return coordinate % period; 72 | } 73 | 74 | private static double interpolate(final double a, final double b, final double c, final double d, final double x) { 75 | final double p = (d - c) - (a - b); 76 | 77 | return x * (x * (x * p + ((a - b) - p)) + (c - a)) + b; 78 | } 79 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/noise/gradient/GaborNoise.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.noise.gradient; 2 | 3 | import supercoder79.simplexterrain.api.noise.Noise; 4 | 5 | import java.util.Random; 6 | 7 | /** 8 | * Please excuse the really weird code here. It was ported over from c++. 9 | * 10 | * @author SirMack, SuperCoder79 11 | */ 12 | public class GaborNoise extends Noise { 13 | InternalNoise internalNoise; 14 | private static final Random rand = new Random(); 15 | 16 | public GaborNoise(long seed) { 17 | super(seed); 18 | internalNoise = new InternalNoise(1.0f, 0.05f, 0.625f, (float) (Math.PI / 4.f), 64f, 256, seed); 19 | } 20 | 21 | @Override 22 | public double sample(double x, double z) { 23 | return internalNoise.operator((float) x,(float) z); 24 | } 25 | 26 | @Override 27 | public double sample(double x, double y, double z) { 28 | return 0; 29 | } 30 | 31 | static class PRNG { 32 | Random r; 33 | 34 | void seed(long s) { 35 | r = new Random(s); 36 | } 37 | 38 | long operator() { 39 | return r.nextLong(); 40 | } 41 | 42 | float uniform_0_1() { 43 | return (float) (operator()) / (float) (Long.MAX_VALUE); 44 | } 45 | 46 | float uniform(float min, float max) { 47 | return min + (uniform_0_1() * (max - min)); 48 | } 49 | 50 | long poisson(float mean) { 51 | float g_ = (float) Math.exp(-mean); 52 | long em = 0; 53 | double t = uniform_0_1(); 54 | while (t > g_) { 55 | ++em; 56 | t *= uniform_0_1(); 57 | } 58 | return em; 59 | } 60 | 61 | // long x_; 62 | } 63 | 64 | static float gabor(float K, float a, float F_0, float omega_0, float x, float y) { 65 | float gaussian_envelop = (float) (K * Math.exp(-Math.PI * (a * a) * ((x * x) + (y * y)))); 66 | float sinusoidal_carrier = (float) Math.cos(2.0 * Math.PI * F_0 * ((x * Math.cos(omega_0)) + (y * Math.sin(omega_0)))); 67 | return gaussian_envelop * sinusoidal_carrier; 68 | } 69 | 70 | static long morton(long x, long y) { 71 | rand.setSeed(31 * x + y); 72 | return rand.nextLong(); 73 | } 74 | 75 | static class InternalNoise { 76 | InternalNoise(float K, float a, float F_0, float omega_0, float number_of_impulses_per_kernel, long period, 77 | long random_offset) { 78 | K_ = K; 79 | a_ = a; 80 | F_0_ = F_0; 81 | omega_0_ = omega_0; 82 | period_ = period; 83 | random_offset_ = random_offset; 84 | kernel_radius_ = (float) (Math.sqrt(-Math.log(0.05) / Math.PI) / a_); 85 | impulse_density_ = (float) (number_of_impulses_per_kernel / (Math.PI * kernel_radius_ * kernel_radius_)); 86 | } 87 | 88 | float operator(float x, float y) { 89 | x /= kernel_radius_; 90 | y /= kernel_radius_; 91 | float int_x = (float) Math.floor(x), int_y = (float) Math.floor(y); 92 | float frac_x = x - int_x, frac_y = y - int_y; 93 | int i = (int) (int_x), j = (int) (int_y); 94 | float noise = 0; 95 | for (int di = -1; di <= +1; ++di) { 96 | for (int dj = -1; dj <= +1; ++dj) { 97 | noise += cell(i + di, j + dj, frac_x - di, frac_y - dj); 98 | } 99 | } 100 | return noise; 101 | } 102 | 103 | float cell(int i, int j, float x, float y) { 104 | // long s = (((long(j) % period_) * period_) + (long(i) % period_)) + random_offset_; // periodic noise 105 | long s = morton(i, j) + random_offset_; // nonperiodic noise 106 | if (s == 0) s = 1; 107 | PRNG prng = new PRNG(); 108 | prng.seed(s); 109 | double number_of_impulses_per_cell = impulse_density_ * kernel_radius_ * kernel_radius_; 110 | long number_of_impulses = prng.poisson((float) number_of_impulses_per_cell); 111 | float noise = 0; 112 | for (long __ = 0; __ < number_of_impulses; ++__) { 113 | float x_i = prng.uniform_0_1(); 114 | float y_i = prng.uniform_0_1(); 115 | x_i = y_i = 0; 116 | float w_i = prng.uniform(-1, +1); 117 | float omega_0_i = prng.uniform(0.0f, (float) (2.0 * Math.PI)); 118 | float x_i_x = x - x_i; 119 | float y_i_y = y - y_i; 120 | if (((x_i_x * x_i_x) + (y_i_y * y_i_y)) < 20.0) { 121 | // noise += w_i * 122 | // gabor(K_, a_, F_0_, omega_0_, x_i_x * kernel_radius_, y_i_y * kernel_radius_); // anisotropic 123 | noise += w_i * gabor(K_, a_, F_0_, omega_0_i, x_i_x * kernel_radius_, y_i_y * kernel_radius_); // isotropic 124 | } 125 | } 126 | return noise; 127 | } 128 | 129 | float variance() { 130 | float integral_gabor_filter_squared = 131 | (float) (((K_ * K_) / (4.0 * a_ * a_)) * (1.0 + Math.exp(-(2.0 * Math.PI * F_0_ * F_0_) / (a_ * a_)))); 132 | return (float) (impulse_density_ * (1.0 / 3.0) * integral_gabor_filter_squared); 133 | } 134 | 135 | float K_; 136 | float a_; 137 | float F_0_; 138 | float omega_0_; 139 | float kernel_radius_; 140 | float impulse_density_; 141 | long period_; 142 | long random_offset_; 143 | } 144 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/noise/gradient/PerlinNoise.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.noise.gradient; 2 | 3 | import supercoder79.simplexterrain.api.noise.Noise; 4 | 5 | /** 6 | * @author Ken Perlin 7 | */ 8 | public class PerlinNoise extends Noise { 9 | public PerlinNoise(long seed) { 10 | super(seed); 11 | } 12 | 13 | @Override 14 | public double sample(double x, double z) { 15 | return sample(x, 0, z); 16 | } 17 | 18 | public double sample(double x, double y, double z) { 19 | int X = (int)Math.floor(x) & 255, // FIND UNIT CUBE THAT 20 | Y = (int)Math.floor(y) & 255, // CONTAINS POINT. 21 | Z = (int)Math.floor(z) & 255; 22 | x -= Math.floor(x); // FIND RELATIVE X,Y,Z 23 | y -= Math.floor(y); // OF POINT IN CUBE. 24 | z -= Math.floor(z); 25 | double u = fade(x), // COMPUTE FADE CURVES 26 | v = fade(y), // FOR EACH OF X,Y,Z. 27 | w = fade(z); 28 | int A = p[X ]+Y, AA = p[A]+Z, AB = p[A+1]+Z, // HASH COORDINATES OF 29 | B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z; // THE 8 CUBE CORNERS, 30 | 31 | return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD 32 | grad(p[BA ], x-1, y , z )), // BLENDED 33 | lerp(u, grad(p[AB ], x , y-1, z ), // RESULTS 34 | grad(p[BB ], x-1, y-1, z ))),// FROM 8 35 | lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ), // CORNERS 36 | grad(p[BA+1], x-1, y , z-1 )), // OF CUBE 37 | lerp(u, grad(p[AB+1], x , y-1, z-1 ), 38 | grad(p[BB+1], x-1, y-1, z-1 )))); 39 | } 40 | 41 | static double fade(double t) { 42 | return t * t * t * (t * (t * 6 - 15) + 10); 43 | } 44 | 45 | static double grad(int hash, double x, double y, double z) { 46 | int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE 47 | double u = h<8 ? x : y, // INTO 12 GRADIENT DIRECTIONS. 48 | v = h<4 ? y : h==12||h==14 ? x : z; 49 | return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v); 50 | } 51 | 52 | static final int p[] = new int[512], permutation[] = { 151,160,137,91,90,15, 53 | 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 54 | 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 55 | 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 56 | 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 57 | 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 58 | 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 59 | 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 60 | 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 61 | 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 62 | 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 63 | 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 64 | 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 65 | }; 66 | static { 67 | for (int i=0; i < 256 ; i++) p[256+i] = p[i] = permutation[i]; 68 | } 69 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/noise/notch/NoiseMap.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.noise.notch; 2 | 3 | import supercoder79.simplexterrain.api.noise.Noise; 4 | 5 | import java.util.*; 6 | 7 | public class NoiseMap extends Noise { 8 | private Random random; 9 | private int levels; 10 | private int fuzz; 11 | 12 | public NoiseMap(long seed) { 13 | super(seed); 14 | this.random = new Random(seed); 15 | this.fuzz = 16; 16 | this.levels = 1; 17 | } 18 | 19 | public int[] read(final int width, final int height) { 20 | final int[] tmp = new int[width * height]; 21 | final int level = this.levels; 22 | for (int step = width >> level, y = 0; y < height; y += step) { 23 | for (int x = 0; x < width; x += step) { 24 | tmp[x + y * width] = (random.nextInt(256) - 128) * this.fuzz; 25 | } 26 | } 27 | for (int step = width >> level; step > 1; step /= 2) { 28 | final int val = 256 * (step << level); 29 | final int ss = step / 2; 30 | for (int y2 = 0; y2 < height; y2 += step) { 31 | for (int x2 = 0; x2 < width; x2 += step) { 32 | final int ul = tmp[(x2 + 0) % width + (y2 + 0) % height * width]; 33 | final int ur = tmp[(x2 + step) % width + (y2 + 0) % height * width]; 34 | final int dl = tmp[(x2 + 0) % width + (y2 + step) % height * width]; 35 | final int dr = tmp[(x2 + step) % width + (y2 + step) % height * width]; 36 | final int m = (ul + dl + ur + dr) / 4 + random.nextInt(val * 2) - val; 37 | tmp[x2 + ss + (y2 + ss) * width] = m; 38 | } 39 | } 40 | for (int y2 = 0; y2 < height; y2 += step) { 41 | for (int x2 = 0; x2 < width; x2 += step) { 42 | final int c = tmp[x2 + y2 * width]; 43 | final int r = tmp[(x2 + step) % width + y2 * width]; 44 | final int d = tmp[x2 + (y2 + step) % width * width]; 45 | final int mu = tmp[(x2 + ss & width - 1) + (y2 + ss - step & height - 1) * width]; 46 | final int ml = tmp[(x2 + ss - step & width - 1) + (y2 + ss & height - 1) * width]; 47 | final int i = tmp[(x2 + ss) % width + (y2 + ss) % height * width]; 48 | final int u = (c + r + i + mu) / 4 + random.nextInt(val * 2) - val; 49 | final int l = (c + d + i + ml) / 4 + random.nextInt(val * 2) - val; 50 | tmp[x2 + ss + y2 * width] = u; 51 | tmp[x2 + (y2 + ss) * width] = l; 52 | } 53 | } 54 | } 55 | final int[] result = new int[width * height]; 56 | for (int y = 0; y < height; ++y) { 57 | for (int x = 0; x < width; ++x) { 58 | result[x + y * width] = tmp[x % width + y % height * width] / 512 + 128; 59 | } 60 | } 61 | return result; 62 | } 63 | 64 | @Override 65 | public double sample(double x, double z) { 66 | return read(16, 16)[0] / 500.0; 67 | } 68 | 69 | @Override 70 | public double sample(double x, double y, double z) { 71 | return 0; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/noise/value/ValueNoise.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.noise.value; 2 | 3 | import net.minecraft.util.math.MathHelper; 4 | import supercoder79.simplexterrain.api.noise.Noise; 5 | 6 | /** 7 | * @author Valoeghese 8 | */ 9 | public final class ValueNoise extends Noise { 10 | private final SimpleRandom rand; 11 | private final boolean fade = true; 12 | 13 | private final double offsetX; 14 | private final double offsetY; 15 | private final double offsetZ; 16 | 17 | public ValueNoise(long seed) { 18 | super(seed); 19 | rand = new SimpleRandom(seed); 20 | rand.init(0, 0); 21 | offsetX = rand.randomDouble(); 22 | offsetY = rand.randomDouble(); 23 | offsetZ = rand.randomDouble(); 24 | } 25 | 26 | private double keyPoint(double x, double y) { 27 | return (2 * rand.randomDouble(x, y)) - 1; 28 | } 29 | 30 | private double keyPoint(double x, double y, double z) { 31 | return (2 * rand.randomDouble(x, y, z)) - 1; 32 | } 33 | 34 | private double sampleImpl(double x, double y) { 35 | double xFloor = MathHelper.floor(x); 36 | double yFloor = MathHelper.floor(y); 37 | 38 | double localX = x - xFloor; 39 | double localY = y - yFloor; 40 | 41 | if (fade) { 42 | localX = fade(localX); 43 | localY = fade(localY); 44 | } 45 | 46 | double NW = keyPoint(xFloor, yFloor + 1); 47 | double NE = keyPoint(xFloor + 1, yFloor + 1); 48 | double SW = keyPoint(xFloor, yFloor); 49 | double SE = keyPoint(xFloor + 1, yFloor); 50 | 51 | return MathHelper.lerp(localY, 52 | MathHelper.lerp(localX, SW, SE), 53 | MathHelper.lerp(localX, NW, NE)); 54 | } 55 | 56 | private double sampleImpl(double x, double y, double z) { 57 | double xFloor = MathHelper.floor(x); 58 | double yFloor = MathHelper.floor(y); 59 | double zFloor = MathHelper.floor(z); 60 | 61 | double localX = x - xFloor; 62 | double localY = y - yFloor; 63 | double localZ = z - zFloor; 64 | 65 | if (fade) { 66 | localX = fade(localX); 67 | localY = fade(localY); 68 | localZ = fade(localZ); 69 | } 70 | 71 | double NWLow = keyPoint(xFloor, yFloor + 1, zFloor); 72 | double NELow = keyPoint(xFloor + 1, yFloor + 1, zFloor); 73 | double SWLow = keyPoint(xFloor, yFloor, zFloor); 74 | double SELow = keyPoint(xFloor + 1, yFloor, zFloor); 75 | 76 | double NWHigh = keyPoint(xFloor, yFloor + 1, zFloor + 1); 77 | double NEHigh = keyPoint(xFloor + 1, yFloor + 1, zFloor + 1); 78 | double SWHigh = keyPoint(xFloor, yFloor, zFloor + 1); 79 | double SEHigh = keyPoint(xFloor + 1, yFloor, zFloor + 1); 80 | 81 | return MathHelper.lerp(localZ, 82 | MathHelper.lerp(localY, 83 | MathHelper.lerp(localX, SWLow, SELow), 84 | MathHelper.lerp(localX, NWLow, NELow)), 85 | MathHelper.lerp(localY, 86 | MathHelper.lerp(localX, SWHigh, SEHigh), 87 | MathHelper.lerp(localX, NWHigh, NEHigh))); 88 | } 89 | 90 | private static double fade(double n) { 91 | return n * n * n * (n * (n * 6 - 15) + 10); 92 | } 93 | 94 | @Override 95 | public double sample(double x, double y) { 96 | return sampleImpl(x + offsetX, y + offsetY); 97 | } 98 | 99 | @Override 100 | public double sample(double x, double y, double z) { 101 | return sampleImpl(x + offsetX, y + offsetY, z + offsetZ); 102 | } 103 | } 104 | 105 | class SimpleRandom { 106 | private long seed; 107 | private long localSeed; 108 | 109 | public SimpleRandom(long seed) { 110 | this.seed = seed; 111 | this.localSeed = seed; 112 | } 113 | 114 | public int random(double x, double y, int bound) { 115 | init(x, y); 116 | 117 | int result = (int) ((localSeed >> 24) % bound); 118 | if (result < 0) { 119 | result += (bound - 1); 120 | } 121 | 122 | return result; 123 | } 124 | 125 | public int random(double x, double y, double z, int bound) { 126 | init(x, y, z); 127 | 128 | int result = (int) ((localSeed >> 24) % bound); 129 | if (result < 0) { 130 | result += (bound - 1); 131 | } 132 | 133 | return result; 134 | } 135 | 136 | public double randomDouble(double x, double y) { 137 | return (double) this.random(x, y, Integer.MAX_VALUE) / (double) Integer.MAX_VALUE; 138 | } 139 | 140 | public double randomDouble(double x, double y, double z) { 141 | return (double) this.random(x, y, z, Integer.MAX_VALUE) / (double) Integer.MAX_VALUE; 142 | } 143 | 144 | public int random(int bound) { 145 | int result = (int) ((localSeed >> 24) % bound); 146 | if (result < 0) { 147 | result += (bound - 1); 148 | } 149 | 150 | localSeed += seed; 151 | localSeed *= 3412375462423L * localSeed + 834672456235L; 152 | 153 | return result; 154 | } 155 | 156 | public double randomDouble() { 157 | return (double) this.random(Integer.MAX_VALUE) / (double) Integer.MAX_VALUE; 158 | } 159 | 160 | public void init(double x, double y) { 161 | localSeed = seed; 162 | localSeed += (x * 72624D); 163 | localSeed *= 3412375462423L * localSeed + 834672456235L; 164 | localSeed += (y * 8963D); 165 | localSeed *= 3412375462423L * localSeed + 834672456235L; 166 | } 167 | 168 | public void init(double x, double y, double z) { 169 | localSeed = seed; 170 | localSeed += (x * 72624D); 171 | localSeed *= 3412375462423L * localSeed + 834672456235L; 172 | localSeed += (y * 8963D); 173 | localSeed *= 3412375462423L * localSeed + 834672456235L; 174 | localSeed += (z * 56385D); 175 | localSeed *= 3412375462423L * localSeed + 834672456235L; 176 | } 177 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/noise/voronoi/VoronoiNoise.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.noise.voronoi; 2 | 3 | import supercoder79.simplexterrain.api.noise.Noise; 4 | 5 | import java.util.Random; 6 | 7 | public class VoronoiNoise extends Noise { 8 | 9 | private static final double SQRT_2 = 1 / 1.4142135623730950488; 10 | private static final double SQRT_3 = 1 / 1.7320508075688772935; 11 | 12 | private long seed; 13 | 14 | 15 | public VoronoiNoise(long seed) { 16 | super(seed); 17 | this.seed = seed; 18 | } 19 | 20 | private double getDistance(double xDist, double zDist) { 21 | return fastSqrt((xDist * xDist) + (zDist * zDist)) * SQRT_2; 22 | } 23 | 24 | private double getDistance(double xDist, double yDist, double zDist) { 25 | return fastSqrt(xDist * xDist + yDist * yDist + zDist * zDist) * SQRT_3; 26 | } 27 | public long getSeed() { 28 | return seed; 29 | } 30 | 31 | @Override 32 | public double sample(double x, double z) { 33 | int xInt = (x > 0 ? (int)x : (int)x - 1); 34 | int zInt = (z > 0 ? (int)z : (int)z - 1); 35 | 36 | double minDist = 32000000.0; 37 | 38 | double xCandidate = 0; 39 | double zCandidate = 0; 40 | 41 | for(int zCur = zInt - 2; zCur <= zInt + 2; zCur++) { 42 | for(int xCur = xInt - 2; xCur <= xInt + 2; xCur++) { 43 | 44 | double xPos = xCur + valueNoise2D(xCur, zCur, seed); 45 | double zPos = zCur + valueNoise2D(xCur, zCur, new Random(seed).nextLong()); 46 | double xDist = xPos - x; 47 | double zDist = zPos - z; 48 | double dist = xDist * xDist + zDist * zDist; 49 | 50 | if(dist < minDist) { 51 | minDist = dist; 52 | xCandidate = xPos; 53 | zCandidate = zPos; 54 | } 55 | } 56 | } 57 | 58 | double xDist = xCandidate - x; 59 | double zDist = zCandidate - z; 60 | 61 | return (getDistance(xDist, zDist) * 2) - 1; 62 | } 63 | 64 | @Override 65 | public double sample(double x, double y, double z) { 66 | 67 | int xInt = (x > 0 ? (int)x : (int)x - 1); 68 | int yInt = (y > 0 ? (int)y : (int)y - 1); 69 | int zInt = (z > 0 ? (int)z : (int)z - 1); 70 | 71 | double minDist = 32000000.0; 72 | 73 | double xCandidate = 0; 74 | double yCandidate = 0; 75 | double zCandidate = 0; 76 | 77 | Random rand = new Random(seed); 78 | 79 | for(int zCur = zInt - 2; zCur <= zInt + 2; zCur++) { 80 | for(int yCur = yInt - 2; yCur <= yInt + 2; yCur++) { 81 | for(int xCur = xInt - 2; xCur <= xInt + 2; xCur++) { 82 | 83 | double xPos = xCur + valueNoise3D (xCur, yCur, zCur, seed); 84 | double yPos = yCur + valueNoise3D (xCur, yCur, zCur, rand.nextLong()); 85 | double zPos = zCur + valueNoise3D (xCur, yCur, zCur, rand.nextLong()); 86 | double xDist = xPos - x; 87 | double yDist = yPos - y; 88 | double zDist = zPos - z; 89 | double dist = xDist * xDist + yDist * yDist + zDist * zDist; 90 | 91 | if(dist < minDist) { 92 | minDist = dist; 93 | xCandidate = xPos; 94 | yCandidate = yPos; 95 | zCandidate = zPos; 96 | } 97 | } 98 | } 99 | } 100 | 101 | double xDist = xCandidate - x; 102 | double yDist = yCandidate - y; 103 | double zDist = zCandidate - z; 104 | 105 | return (getDistance(xDist, yDist, zDist) * 2) - 1; 106 | } 107 | 108 | public static double valueNoise2D(int x, int z, long seed) { 109 | long n = (1619 * x + 6971 * z + 1013 * seed) & 0x7fffffff; 110 | n = (n >> 13) ^ n; 111 | return 1.0 - ((double)((n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff) / 1073741824.0); 112 | } 113 | 114 | public static double valueNoise3D(int x, int y, int z, long seed) { 115 | long n = (1619 * x + 31337 * y + 6971 * z + 1013 * seed) & 0x7fffffff; 116 | n = (n >> 13) ^ n; 117 | return 1.0 - ((double)((n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff) / 1073741824.0); 118 | } 119 | 120 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/noise/worley/WorleyNoise.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.noise.worley; 2 | 3 | /* 4 | * This code is released into the public domain. 5 | * It is a conversion of Matt Pharr's original C++ implementation. 6 | * The licensing of the original code follows: 7 | * 8 | * /* 9 | * * wnoise.cpp 10 | * * 11 | * * Copyright (C) 1998, Matt Pharr 12 | * * 13 | * * This software is placed in the public domain and is provided as is 14 | * * without express or implied warranty. 15 | * * 16 | * * Basic implementation of Steve Worley's noise function; see proceedings 17 | * * of SIGGRAPH 96. 18 | * */ 19 | */ 20 | 21 | import supercoder79.simplexterrain.api.noise.Noise; 22 | 23 | /** 24 | * This is an implementation of Steve Worley's cellular noise function. It is 25 | * derived (heavily) from Matt Pharr's public domain implementation, and in the 26 | * spirit of that donation this version remains in the public domain. 27 | *

28 | * Here is the original licensing information: 29 | * 30 | *

 31 |  * /*
 32 |  *  * wnoise.cpp
 33 |  *  *
 34 |  *  * Copyright (C) 1998, Matt Pharr <mmp@graphics.stanford.edu>
 35 |  *  *
 36 |  *  * This software is placed in the public domain and is provided as is without
 37 |  *  * express or implied warranty.
 38 |  *  *
 39 |  *  * Basic implementation of Steve Worley's noise function; see proceedings of
 40 |  *  * SIGGRAPH 96.
 41 |  *  */
 42 |  * 
43 | * 44 | * Some features (like variable density) have been removed for simplicity. 45 | *

46 | * Instances of this class are immutable and threadsafe. 47 | * 48 | * @author saybur 49 | * 50 | */ 51 | public class WorleyNoise extends Noise { 52 | /** 53 | * Represents a point in three dimensional space. 54 | * 55 | * @author saybur 56 | * 57 | */ 58 | private static final class Point { 59 | private final double x; 60 | private final double z; 61 | 62 | /** 63 | * Creates a point at location (x, z). 64 | * 65 | * @param x 66 | * the x coordinate of the point. 67 | * @param z 68 | * the z coordinate of the point. 69 | */ 70 | private Point(double x, double z) { 71 | this.x = x; 72 | this.z = z; 73 | } 74 | 75 | /** 76 | * Provides a fast distance calculation between two points. This is done by 77 | * not taking the square root of the result. 78 | * 79 | * @param other 80 | * the coordinate to calculate distance to. 81 | * @return the distance between this point and the provided point. 82 | */ 83 | public double distanceSquared(Point other) { 84 | double x2 = x - other.x; 85 | double z2 = z - other.z; 86 | return x2 * x2 + z2 * z2; 87 | } 88 | } 89 | 90 | private static int floor(double n) { 91 | return n > 0 ? (int) n : (int) n - 1; 92 | } 93 | 94 | private static double frac(double n) { 95 | return n >= 0 ? n - (int) (n) : frac(-n); 96 | } 97 | 98 | /** 99 | * Checks all voxels near the origin for the closest point to the origin. 100 | * The returned value will be the distance to the closest point. 101 | */ 102 | private static double minimumDistance(XorShift.Instance r, Point origin) { 103 | // hack, but easier than handling points that are exactly at negative 104 | // integer latice-points correctly. 105 | Point p = new Point(origin.x + 1e-7, origin.z + 1e-7); 106 | // get the coordinate that this point resides at 107 | int x = floor(p.x); 108 | // int y = floor(p.y); 109 | int z = floor(p.z); 110 | // create storage to track lowest values 111 | double s = Double.MAX_VALUE; 112 | // first check voxel the point is in 113 | s = processVoxel(r, p, s, x, z); 114 | // check each of the voxels that share a face with the 115 | // point's voxel, if they're close enough to possibly 116 | // make a difference 117 | // squared distance to the voxel in the +x direction 118 | double dpx2 = p.x >= 0. ? square(1.0 - frac(p.x)) : square(frac(p.x)); 119 | if(dpx2 < s) { 120 | s = processVoxel(r, p, s, x + 1, z); 121 | } 122 | // -x 123 | double dnx2 = p.x >= 0. ? square(frac(p.x)) : square(1. - frac(p.x)); 124 | if(dnx2 < s) { 125 | s = processVoxel(r, p, s, x - 1, z); 126 | } 127 | 128 | //We can safely ignore the y value, improving the performance 129 | 130 | // // +y 131 | // double dpy2 = p.y >= 0. ? square(1. - frac(p.y)) : square(frac(p.y)); 132 | // if(dpy2 < s) { 133 | // s = processVoxel(r, p, s, x, y + 1, z); 134 | // } 135 | // // -y 136 | // double dny2 = p.y >= 0. ? square(frac(p.y)) : square(1. - frac(p.y)); 137 | // if(dny2 < s) { 138 | // s = processVoxel(r, p, s, x, y - 1, z); 139 | // } 140 | 141 | // +z 142 | double dpz2 = p.z >= 0. ? square(1. - frac(p.z)) : square(frac(p.z)); 143 | if(dpz2 < s) { 144 | s = processVoxel(r, p, s, x, z + 1); 145 | } 146 | // -z 147 | double dnz2 = p.z >= 0. ? square(frac(p.z)) : square(1. - frac(p.z)); 148 | if(dnz2 < s) { 149 | s = processVoxel(r, p, s, x, z - 1); 150 | } 151 | // finally check the remaining adjacent voxels 152 | for(int i = -1; i <= 1; ++i) { 153 | // for(int j = -1; j <= 1; ++j) { 154 | for(int k = -1; k <= 1; ++k) { 155 | // don't check the ones we already did above 156 | if(Noise.fastAbs(i) + /*Math.abs(j)*/ + Noise.fastAbs(k) <= 1) { 157 | continue; 158 | } 159 | // find squared distance to voxel 160 | double vd2 = 0; 161 | if(i < 0) 162 | vd2 += dnx2; 163 | else if(i > 0) 164 | vd2 += dpx2; 165 | // if(j < 0) 166 | // vd2 += dny2; 167 | // else if(j > 0) 168 | // vd2 += dpy2; 169 | if(k < 0) 170 | vd2 += dnz2; 171 | else if(k > 0) 172 | vd2 += dpz2; 173 | // and check it if it's close enough to matter 174 | if(vd2 < s) 175 | { 176 | s = processVoxel(r, p, s, x + i, z + k); 177 | } 178 | } 179 | // } 180 | } 181 | // provide minimum. be sure to square root it to get the 182 | // true distance. 183 | 184 | return Math.sqrt(s); 185 | } 186 | 187 | /** 188 | * Processes a voxel and calculates the distances of the points within 189 | * against the provided point. It also tracks the progress of the lowest 190 | * values yet discovered. 191 | * 192 | * @param r 193 | * the random number generator. 194 | * @param p 195 | * the point that the locations within this voxel will be tested 196 | * against. 197 | * @param s 198 | * the storage that tracks the lowest values currently 199 | * encountered. 200 | * @param x 201 | * the x coordinate of the voxel. 202 | * @param z 203 | * the z coordinate of the voxel. 204 | * @return the closest distance of the points within the voxel to the 205 | * provided point. 206 | */ 207 | private static double processVoxel(XorShift.Instance r, Point p, double s, int x, int z) { 208 | // reset random number generator for the voxel 209 | r.setSeed(x, z); 210 | // each voxel always has one point 211 | // Point created = new Point( 212 | // x + r.nextDouble(), 213 | // y + r.nextDouble(), 214 | // z + r.nextDouble()); 215 | Point created = new Point( 216 | x + r.nextDouble(), 217 | z + r.nextDouble()); 218 | // determine the distance between the generated point 219 | // and the source point we're checking. 220 | double distance = p.distanceSquared(created); 221 | // add distance if it is lowest 222 | return Math.min(distance, s); 223 | } 224 | 225 | private static double square(double n) { 226 | return n * n; 227 | } 228 | 229 | private final XorShift randomFactory; 230 | 231 | public WorleyNoise(long seed) { 232 | super(seed); 233 | randomFactory = XorShift.create(seed); 234 | } 235 | 236 | /** 237 | * Gets the noise value at the provided location. 238 | * 239 | * @param x 240 | * the x coordinate. 241 | * @param y 242 | * the y coordinate. 243 | * @param z 244 | * the z coordinate. 245 | * @return the noise value at the coordinate. 246 | */ 247 | private double noise(double x, double y, double z) { 248 | return minimumDistance(randomFactory.getInstance(), new Point(x, z)); 249 | } 250 | 251 | @Override 252 | public double sample(double x, double z) { 253 | return noise(x, 0, z); 254 | } 255 | 256 | @Override 257 | public double sample(double x, double y, double z) { 258 | return noise(x, y, z); 259 | } 260 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/noise/worley/XorShift.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.noise.worley; 2 | 3 | import java.util.Objects; 4 | import java.util.Random; 5 | import java.util.concurrent.ThreadLocalRandom; 6 | 7 | import supercoder79.simplexterrain.api.noise.Noise; 8 | 9 | /** 10 | * Random number generator for voxel-based fractals based on the XorShift 11 | * pseudo-random number generator described by George Marsaglia in his paper 12 | * XorShift RNGs (http://www.jstatsoft.org/v08/i14/paper). 14 | *

15 | * This particular implementation has a period of 2 ^ 96 - 1 and 16 | * uses Marsaglia's triple of [13, 19, 3]. For use in cellular noise functions, 17 | * it has a method for resetting the generator state via 18 | * {@link Instance#setSeed(long, long, long)} for x, y, z voxel 19 | * coordinates, which will wrap on [0, 1024) for each of x, y, z. 20 | *

21 | * Objects of XorShift.Instance are not threadsafe. 22 | * Concurrent access should be externally synchronized or use separate 23 | * instances. XorShift itself is threadsafe. 24 | * 25 | * @author saybur 26 | * 27 | */ 28 | public class XorShift { 29 | /** 30 | * Random number generator instance for XorShift. See the class 31 | * documentation for details. 32 | *

33 | * A reminder: this is not threadsafe. 34 | * 35 | * @author saybur 36 | * 37 | */ 38 | public final class Instance { 39 | private long x, z; 40 | 41 | private Instance() { 42 | setSeed(0, 0); 43 | } 44 | 45 | /** 46 | * Provides a pseudo-random double value on [0.0, 1.0). 47 | * 48 | * @return the next double value. 49 | */ 50 | public double nextDouble() { 51 | // get out of signed range, then divide in the remaining space 52 | // of the shifted long value. i hope this works... 53 | return (nextLong() >>> 2) * (1.0 / (1L << 62)); 54 | } 55 | 56 | /** 57 | * Provides a pseudo-random long value. 58 | * 59 | * @return the next long value. 60 | */ 61 | public long nextLong() { 62 | long t; 63 | t = (x ^ (x << 13)); 64 | x = z; 65 | z = (z ^ (z >>> 3)) ^ (t ^ t >>> 19); 66 | return z; 67 | } 68 | 69 | /** 70 | * Sets the seed for this number generator to the given values. 71 | *

72 | * This is for the cellular noise functions and may be ignored by other 73 | * users, as the constructor will initialize the generator with random 74 | * starting values. 75 | * 76 | * @param x 77 | * the X component. 78 | * @param z 79 | * the Z component. 80 | */ 81 | public void setSeed(long x, long z) { 82 | this.x = seeds[(int) (Noise.fastAbs(x) % SEED_TABLE_SPACE)]; 83 | // this.y = seeds[(int) (Noise.fastAbs(y) % SEED_TABLE_SPACE) 84 | // + SEED_TABLE_SPACE]; 85 | this.z = seeds[(int) (Noise.fastAbs(z) % SEED_TABLE_SPACE) 86 | + SEED_TABLE_SPACE + SEED_TABLE_SPACE]; 87 | 88 | // if (!SimplexTerrain.CONFIG.sacrificeAccuracyForSpeed) { 89 | // // decreases spherical artifacts, but obviously is slow 90 | // // TODO replace by fixing underlying issue 91 | // for (int i = 0; i < 5; i++) 92 | // nextLong(); 93 | // } 94 | } 95 | } 96 | 97 | /** 98 | * The space for each of x, y, and z in the seeds table. 99 | */ 100 | private static final int SEED_TABLE_SPACE = 1024; 101 | /** 102 | * The final size of the seeds table. 103 | */ 104 | private static final int SEED_TABLE_SIZE = SEED_TABLE_SPACE * 3; 105 | 106 | /** 107 | * Creates a new random number generator factory with a random seed value. 108 | * 109 | * @return the random number generator factory. 110 | */ 111 | public static XorShift create() { 112 | return new XorShift(ThreadLocalRandom.current().nextLong()); 113 | } 114 | 115 | /** 116 | * Creates a new random number generator factory with the given seed value. 117 | * 118 | * @param seed 119 | * the seed value. 120 | * @return the random number generator factory. 121 | */ 122 | public static XorShift create(long seed) { 123 | return new XorShift(seed); 124 | } 125 | 126 | private final long[] seeds; 127 | 128 | private XorShift(long seed) { 129 | Random random = new Random(seed); 130 | seeds = new long[SEED_TABLE_SIZE]; 131 | for(int i = 0; i < SEED_TABLE_SIZE; i++) { 132 | seeds[i] = random.nextLong(); 133 | } 134 | } 135 | 136 | @Override 137 | public boolean equals(Object obj) { 138 | if(obj instanceof XorShift) { 139 | XorShift o = (XorShift) obj; 140 | return Objects.equals(seeds, o.seeds); 141 | } 142 | else { 143 | return false; 144 | } 145 | } 146 | 147 | /** 148 | * Creates a new random number generator instance. 149 | *

150 | * Each instance should be used by a single thread only. See the class 151 | * documentation for information about the generator itself. 152 | * 153 | * @return a new random number generator instance. 154 | */ 155 | public XorShift.Instance getInstance() { 156 | return new XorShift.Instance(); 157 | } 158 | 159 | @Override 160 | public int hashCode() { 161 | return Objects.hash(seeds); 162 | } 163 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/BiomeData.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world; 2 | 3 | /** 4 | * Extra data for biome generation at a specific x/z coordinate. 5 | * This can be used to set specific biomes, force generation, and do other tasks. 6 | */ 7 | public class BiomeData { 8 | private int height = 0; 9 | private boolean river = false; 10 | private boolean mushroomIsland = false; 11 | private boolean forcedLowlands = false; 12 | 13 | public void setHeight(int height) { 14 | this.height = height; 15 | } 16 | 17 | public int getHeight() { 18 | return height; 19 | } 20 | 21 | public void setRiver() { 22 | this.river = true; 23 | } 24 | 25 | public boolean isRiver() { 26 | return river; 27 | } 28 | 29 | public boolean isMushroomIsland() { 30 | return mushroomIsland; 31 | } 32 | 33 | public void setMushroomIsland() { 34 | this.mushroomIsland = true; 35 | } 36 | 37 | public boolean isForcedLowlands() { 38 | return forcedLowlands; 39 | } 40 | 41 | public void setForcedLowlands() { 42 | this.forcedLowlands = true; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/README.md: -------------------------------------------------------------------------------- 1 | ## SuperCoder's random reference for worldgen stuff 2 | 3 | 4 | ### Subchunk Position 5 | 6 | `v` = x or z position 7 | Subchunk: `v >> 2` 8 | to blockpos: `v << 2` 9 | from blockpos to position in chunk: `v & 15` 10 | 11 | ### Caching 12 | * Cache noise modifiers (called multiple times per blockpos) 13 | * Do not cache post processors (called once per blockpos) -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/SimplexWorldType.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world; 2 | 3 | import net.minecraft.client.world.GeneratorType; 4 | import net.minecraft.util.registry.Registry; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.gen.chunk.ChunkGenerator; 7 | import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; 8 | import supercoder79.simplexterrain.world.gen.SimplexBiomeSource; 9 | import supercoder79.simplexterrain.world.gen.SimplexChunkGenerator; 10 | 11 | public class SimplexWorldType extends GeneratorType { 12 | public SimplexWorldType() { 13 | super("simplex"); 14 | GeneratorType.VALUES.add(this); 15 | } 16 | 17 | @Override 18 | protected ChunkGenerator getChunkGenerator(Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed) { 19 | return new SimplexChunkGenerator(new SimplexBiomeSource(biomeRegistry, seed), seed); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/biome/BiomePicker.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.biome; 2 | 3 | import java.util.List; 4 | 5 | import com.google.common.collect.Lists; 6 | 7 | import net.minecraft.util.Identifier; 8 | import net.minecraft.util.registry.Registry; 9 | import net.minecraft.world.biome.Biome; 10 | import net.minecraft.world.biome.layer.util.LayerRandomnessSource; 11 | 12 | /** 13 | * Picks a biome. Pretty self explanatory. 14 | * 15 | * @author Valoeghese 16 | */ 17 | public class BiomePicker { 18 | private final List biomeEntries = Lists.newArrayList(); 19 | private double weightTotal; 20 | 21 | public Identifier pickBiome(LayerRandomnessSource rand) { 22 | double randVal = target(rand); 23 | int i = -1; 24 | 25 | while (randVal >= 0) { 26 | ++i; 27 | randVal -= biomeEntries.get(i).weight; 28 | } 29 | 30 | return biomeEntries.get(i).biomeId; 31 | } 32 | 33 | public void addBiome(Identifier biome, double weight) { 34 | this.biomeEntries.add(new Entry(biome, weight)); 35 | weightTotal += weight; 36 | } 37 | 38 | private double target(LayerRandomnessSource random) { 39 | return (double) random.nextInt(Integer.MAX_VALUE) * weightTotal / Integer.MAX_VALUE; 40 | } 41 | 42 | public static class Entry { 43 | private final Identifier biomeId; 44 | private final double weight; 45 | public Entry(Identifier biome, double weight) { 46 | this.biomeId = biome; 47 | this.weight = weight; 48 | } 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/biome/SimplexBiomesImpl.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.biome; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import net.minecraft.util.Identifier; 7 | import net.minecraft.util.Pair; 8 | import net.minecraft.util.registry.Registry; 9 | import net.minecraft.world.biome.Biome; 10 | import supercoder79.simplexterrain.api.biomes.SimplexClimate; 11 | 12 | public final class SimplexBiomesImpl { 13 | private SimplexBiomesImpl() { 14 | } 15 | 16 | private static final Map lowlandBiomes = new HashMap<>(); 17 | private static final Map midlandBiomes = new HashMap<>(); 18 | private static final Map highlandBiomes = new HashMap<>(); 19 | private static final Map mountainPeaksBiomes = new HashMap<>(); 20 | 21 | private static final Map> replacementBiomes = new HashMap<>(); 22 | 23 | public static void addToLowlands(Identifier biome, SimplexClimate climate, double weight) { 24 | lowlandBiomes.computeIfAbsent(climate, simplexClimate -> new BiomePicker()).addBiome(biome, weight); 25 | } 26 | public static void addToMidlands(Identifier biome, SimplexClimate climate, double weight) { 27 | midlandBiomes.computeIfAbsent(climate, simplexClimate -> new BiomePicker()).addBiome(biome, weight); 28 | } 29 | public static void addToHighlands(Identifier biome, SimplexClimate climate, double weight) { 30 | highlandBiomes.computeIfAbsent(climate, simplexClimate -> new BiomePicker()).addBiome(biome, weight); 31 | } 32 | public static void addToMountainPeaks(Identifier biome, SimplexClimate climate, double weight) { 33 | mountainPeaksBiomes.computeIfAbsent(climate, simplexClimate -> new BiomePicker()).addBiome(biome, weight); 34 | } 35 | 36 | public static void addReplacementBiome(Identifier biomeToReplace, Identifier replacement, int chance) { 37 | // replacementBiomes.put(Registry.BIOME.get(biomeToReplace), new Pair<>(Registry.BIOME.get(replacement), chance)); 38 | } 39 | 40 | public static BiomePicker getLowlandsBiomePicker(SimplexClimate climate) { 41 | return lowlandBiomes.get(climate); 42 | } 43 | public static BiomePicker getMidlandsBiomePicker(SimplexClimate climate) { 44 | return midlandBiomes.get(climate); 45 | } 46 | public static BiomePicker getHighlandsBiomePicker(SimplexClimate climate) { 47 | return highlandBiomes.get(climate); 48 | } 49 | public static BiomePicker getMountainPeaksBiomePicker(SimplexClimate climate) { 50 | return mountainPeaksBiomes.get(climate); 51 | } 52 | 53 | public static Map> getReplacementBiomes() { 54 | return replacementBiomes; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/biomelayers/SimplexBiomeLayers.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.biomelayers; 2 | 3 | import java.util.function.LongFunction; 4 | 5 | import net.minecraft.util.registry.Registry; 6 | import net.minecraft.world.biome.Biome; 7 | import net.minecraft.world.biome.layer.ScaleLayer; 8 | import net.minecraft.world.biome.layer.type.ParentedLayer; 9 | import net.minecraft.world.biome.layer.util.CachingLayerContext; 10 | import net.minecraft.world.biome.layer.util.LayerFactory; 11 | import net.minecraft.world.biome.layer.util.LayerSampleContext; 12 | import net.minecraft.world.biome.layer.util.LayerSampler; 13 | import net.minecraft.world.biome.source.BiomeLayerSampler; 14 | import supercoder79.simplexterrain.world.biomelayers.layers.*; 15 | 16 | public class SimplexBiomeLayers { 17 | private static > LayerFactory stack(long l, ParentedLayer parentedLayer, LayerFactory layerFactory, int i, LongFunction longFunction) { 18 | LayerFactory result = layerFactory; 19 | 20 | for(int j = 0; j < i; ++j) { 21 | result = parentedLayer.create(longFunction.apply(l + (long)j), result); 22 | } 23 | 24 | return result; 25 | } 26 | 27 | private static > LayerFactory build(Registry biomes, long worldSeed, LongFunction contextProvider) { 28 | LayerFactory layer = new SimplexClimateLayer(worldSeed).create(contextProvider.apply(1L)); 29 | layer = new BaseBiomesLayer(biomes).create(contextProvider.apply(5L), layer); 30 | layer = stack(1000, ScaleLayer.NORMAL, layer, 7, contextProvider); 31 | 32 | return layer; 33 | } 34 | 35 | public static BiomeLayerSampler build(Registry biomes, long seed) { 36 | return new BiomeLayerSampler(build(biomes, seed, salt -> new CachingLayerContext(5, seed, salt))); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/biomelayers/layers/BaseBiomesLayer.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.biomelayers.layers; 2 | 3 | import net.minecraft.util.registry.Registry; 4 | import net.minecraft.world.biome.Biome; 5 | import net.minecraft.world.biome.BiomeKeys; 6 | import net.minecraft.world.biome.layer.type.IdentitySamplingLayer; 7 | import net.minecraft.world.biome.layer.util.LayerRandomnessSource; 8 | 9 | public class BaseBiomesLayer implements IdentitySamplingLayer { 10 | private final Registry registry; 11 | 12 | public BaseBiomesLayer(Registry registry) { 13 | 14 | this.registry = registry; 15 | } 16 | 17 | @Override 18 | public int sample(LayerRandomnessSource context, int value) { 19 | if (context.nextInt(4) == 0) { 20 | return this.registry.getRawId(this.registry.get(BiomeKeys.DESERT)); 21 | } 22 | 23 | return this.registry.getRawId(context.nextInt(3) == 0 ? this.registry.get(BiomeKeys.FOREST) : this.registry.get(BiomeKeys.PLAINS)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/biomelayers/layers/ClimateTransformerLayer.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.biomelayers.layers; 2 | 3 | import java.util.function.ToIntFunction; 4 | 5 | import net.minecraft.util.registry.Registry; 6 | import net.minecraft.world.biome.Biome; 7 | import net.minecraft.world.biome.layer.type.IdentitySamplingLayer; 8 | import net.minecraft.world.biome.layer.util.LayerRandomnessSource; 9 | import supercoder79.simplexterrain.api.biomes.SimplexClimate; 10 | 11 | public class ClimateTransformerLayer implements IdentitySamplingLayer { 12 | 13 | public static ClimateTransformerLayer shore(Registry biomes) { 14 | return new ClimateTransformerLayer(climate -> biomes.getRawId(biomes.get(climate.oceanSet.shore))); 15 | } 16 | 17 | public static ClimateTransformerLayer ocean(Registry biomes) { 18 | return new ClimateTransformerLayer(climate -> biomes.getRawId(biomes.get(climate.oceanSet.ocean))); 19 | } 20 | 21 | public static ClimateTransformerLayer deepOcean(Registry biomes) { 22 | return new ClimateTransformerLayer(climate -> biomes.getRawId(biomes.get(climate.oceanSet.deepOcean))); 23 | } 24 | 25 | private final ToIntFunction transformer; 26 | 27 | ClimateTransformerLayer(ToIntFunction transformer) { 28 | this.transformer = transformer; 29 | } 30 | 31 | @Override 32 | public int sample(LayerRandomnessSource rand, int value) { 33 | return this.transformer.applyAsInt(SimplexClimateLayer.REVERSE_ID_MAP[value]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/biomelayers/layers/SimplexClimateLayer.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.biomelayers.layers; 2 | 3 | import java.util.Random; 4 | 5 | import net.minecraft.world.biome.layer.type.InitLayer; 6 | import net.minecraft.world.biome.layer.util.LayerRandomnessSource; 7 | import supercoder79.simplexterrain.SimplexTerrain; 8 | import supercoder79.simplexterrain.api.biomes.SimplexClimate; 9 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 10 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 11 | 12 | public class SimplexClimateLayer implements InitLayer { 13 | private OctaveNoiseSampler temperatureNoise; 14 | private OctaveNoiseSampler humidityNoise; 15 | 16 | private final long worldSeed; 17 | 18 | private int tempOffsetX; 19 | private int tempOffsetZ; 20 | private int humidityOffsetX; 21 | private int humidityOffsetZ; 22 | 23 | private static final Random RAND = new Random(); 24 | 25 | public SimplexClimateLayer(long worldSeed) { 26 | this.worldSeed = worldSeed; 27 | this.initialiseNoise(); 28 | } 29 | 30 | public void initialiseNoise() { 31 | RAND.setSeed(worldSeed); 32 | tempOffsetX = RAND.nextInt(10000); 33 | tempOffsetZ = RAND.nextInt(10000); 34 | humidityOffsetX = RAND.nextInt(10000); 35 | humidityOffsetZ = RAND.nextInt(10000); 36 | temperatureNoise = new OctaveNoiseSampler<>(OpenSimplexNoise.class, RAND, SimplexTerrain.CONFIG.temperatureOctaveAmount, SimplexTerrain.CONFIG.temperatureFrequency, SimplexTerrain.CONFIG.temperatureAmplitude, SimplexTerrain.CONFIG.temperatureAmplitude); 37 | humidityNoise = new OctaveNoiseSampler<>(OpenSimplexNoise.class, RAND, SimplexTerrain.CONFIG.humidityOctaveAmount, SimplexTerrain.CONFIG.humidityFrequency, SimplexTerrain.CONFIG.humidityAmplitude, SimplexTerrain.CONFIG.humidityAmplitude); 38 | } 39 | 40 | @Override 41 | public int sample(LayerRandomnessSource rand, int x, int z) { 42 | double temperature = temperatureNoise.sample(tempOffsetX + x, tempOffsetZ + z) + SimplexTerrain.CONFIG.temperatureOffset; 43 | double humidity = humidityNoise.sample(humidityOffsetX + x, humidityOffsetZ + z) + SimplexTerrain.CONFIG.humidityOffset; 44 | 45 | return SimplexClimate.fromTemperatureHumidity(temperature, humidity).id; 46 | } 47 | 48 | public static final SimplexClimate[] REVERSE_ID_MAP = new SimplexClimate[10]; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/blend/CachingBlender.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.blend; 2 | 3 | import it.unimi.dsi.fastutil.HashCommon; 4 | import net.minecraft.util.math.ChunkPos; 5 | 6 | import java.util.Arrays; 7 | 8 | public final class CachingBlender { 9 | private final long[] keys; 10 | private final LinkedBiomeWeightMap[] values; 11 | private final ScatteredBiomeBlender internal; 12 | 13 | public CachingBlender(double samplingFrequency, double blendRadiusPadding, int chunkWidth) { 14 | this.internal = new ScatteredBiomeBlender(samplingFrequency, blendRadiusPadding, chunkWidth); 15 | 16 | this.keys = new long[512]; 17 | this.values = new LinkedBiomeWeightMap[512]; 18 | 19 | Arrays.fill(this.keys, Long.MIN_VALUE); 20 | } 21 | 22 | public LinkedBiomeWeightMap getBlendForChunk(long seed, int chunkBaseWorldX, int chunkBaseWorldZ, ScatteredBiomeBlender.BiomeEvaluationCallback callback) { 23 | long key = key(chunkBaseWorldX, chunkBaseWorldZ); 24 | int idx = hash(key) & 511; 25 | 26 | if (this.keys[idx] == key) { 27 | return this.values[idx]; 28 | } 29 | 30 | LinkedBiomeWeightMap weightMap = this.internal.getBlendForChunk(seed, chunkBaseWorldX, chunkBaseWorldZ, callback); 31 | this.values[idx] = weightMap; 32 | this.keys[idx] = key; 33 | 34 | return weightMap; 35 | } 36 | 37 | private static int hash(long key) { 38 | return (int) HashCommon.mix(key); 39 | } 40 | 41 | private static long key(int x, int z) { 42 | return ChunkPos.toLong(x, z); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/blend/ChunkPointGatherer.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.blend; 2 | 3 | import java.util.List; 4 | 5 | public class ChunkPointGatherer { 6 | 7 | private static final double CHUNK_RADIUS_RATIO = Math.sqrt(1.0 / 2.0); 8 | 9 | int halfChunkWidth; 10 | double maxPointContributionRadius; 11 | double maxPointContributionRadiusSq; 12 | double radiusPlusHalfChunkWidth; 13 | UnfilteredPointGatherer unfilteredPointGatherer; 14 | 15 | public ChunkPointGatherer(double frequency, double maxPointContributionRadius, int chunkWidth) { 16 | this.halfChunkWidth = chunkWidth / 2; 17 | this.maxPointContributionRadius = maxPointContributionRadius; 18 | this.maxPointContributionRadiusSq = maxPointContributionRadius * maxPointContributionRadius; 19 | this.radiusPlusHalfChunkWidth = maxPointContributionRadius + halfChunkWidth; 20 | unfilteredPointGatherer = new UnfilteredPointGatherer(frequency, 21 | maxPointContributionRadius + chunkWidth * CHUNK_RADIUS_RATIO); 22 | } 23 | 24 | public List> getPointsFromChunkBase(long seed, int chunkBaseWorldX, int chunkBaseWorldZ) { 25 | // Technically, the true minimum is between coordinates. But tests showed it was more efficient to add before converting to doubles. 26 | return getPointsFromChunkCenter(seed, chunkBaseWorldX + halfChunkWidth, chunkBaseWorldZ + halfChunkWidth); 27 | } 28 | 29 | public List> getPointsFromChunkCenter(long seed, int chunkCenterWorldX, int chunkCenterWorldZ) { 30 | List> worldPoints = 31 | unfilteredPointGatherer.getPoints(seed, chunkCenterWorldX, chunkCenterWorldZ); 32 | for (int i = 0; i < worldPoints.size(); i++) { 33 | GatheredPoint point = worldPoints.get(i); 34 | 35 | // Check if point contribution radius lies outside any coordinate in the chunk 36 | double axisCheckValueX = Math.abs(point.getX() - chunkCenterWorldX) - halfChunkWidth; 37 | double axisCheckValueZ = Math.abs(point.getZ() - chunkCenterWorldZ) - halfChunkWidth; 38 | if (axisCheckValueX >= maxPointContributionRadius || axisCheckValueZ >= maxPointContributionRadius 39 | || (axisCheckValueX > 0 && axisCheckValueZ > 0 40 | && axisCheckValueX*axisCheckValueX + axisCheckValueZ*axisCheckValueZ >= maxPointContributionRadiusSq)) { 41 | 42 | // If so, remove it. 43 | // Copy the last value to this value, and remove the last, 44 | // to avoid shifting because order doesn't matter. 45 | int lastIndex = worldPoints.size() - 1; 46 | worldPoints.set(i, worldPoints.get(lastIndex)); 47 | worldPoints.remove(lastIndex); 48 | i--; 49 | } 50 | } 51 | 52 | return worldPoints; 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/blend/GatheredPoint.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.blend; 2 | 3 | public class GatheredPoint { 4 | private double x, z; 5 | private int hash; 6 | private T tag; 7 | 8 | public GatheredPoint(double x, double z, int hash) { 9 | this.x = x; 10 | this.z = z; 11 | this.hash = hash; 12 | } 13 | 14 | public double getX() { 15 | return x; 16 | } 17 | 18 | public double getZ() { 19 | return z; 20 | } 21 | 22 | public double getHash() { 23 | return hash; 24 | } 25 | 26 | public T getTag() { 27 | return tag; 28 | } 29 | 30 | public void setTag(T tag) { 31 | this.tag = tag; 32 | } 33 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/blend/LinkedBiomeWeightMap.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.blend; 2 | 3 | public class LinkedBiomeWeightMap { 4 | private int biome; 5 | private double[] weights; 6 | private LinkedBiomeWeightMap next; 7 | 8 | public LinkedBiomeWeightMap(int biome, LinkedBiomeWeightMap next) { 9 | this.biome = biome; 10 | this.next = next; 11 | } 12 | 13 | public LinkedBiomeWeightMap(int biome, int chunkColumnCount, LinkedBiomeWeightMap next) { 14 | this.biome = biome; 15 | this.weights = new double[chunkColumnCount]; 16 | this.next = next; 17 | } 18 | 19 | public int getBiome() { 20 | return biome; 21 | } 22 | 23 | public double[] getWeights() { 24 | return weights; 25 | } 26 | 27 | public void setWeights(double[] weights) { 28 | this.weights = weights; 29 | } 30 | 31 | public LinkedBiomeWeightMap getNext() { 32 | return next; 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/blend/ScatteredBiomeBlender.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.blend; 2 | 3 | import java.util.List; 4 | 5 | public class ScatteredBiomeBlender { 6 | 7 | private final int chunkColumnCount; 8 | private final int blendRadiusBoundArrayCenter; 9 | private final double chunkWidthMinusOne; 10 | private final double blendRadius, blendRadiusSq; 11 | private final double[] blendRadiusBound; 12 | private final ChunkPointGatherer gatherer; 13 | 14 | // chunkWidth should be a power of two. 15 | public ScatteredBiomeBlender(double samplingFrequency, double blendRadiusPadding, int chunkWidth) { 16 | this.chunkWidthMinusOne = chunkWidth - 1; 17 | this.chunkColumnCount = chunkWidth * chunkWidth; 18 | this.blendRadius = blendRadiusPadding + getInternalMinBlendRadiusForFrequency(samplingFrequency); 19 | this.blendRadiusSq = blendRadius * blendRadius; 20 | this.gatherer = new ChunkPointGatherer<>(samplingFrequency, blendRadius, chunkWidth); 21 | 22 | blendRadiusBoundArrayCenter = (int)Math.ceil(blendRadius) - 1; 23 | blendRadiusBound = new double[blendRadiusBoundArrayCenter * 2 + 1]; 24 | for (int i = 0; i < blendRadiusBound.length; i++) { 25 | int dx = i - blendRadiusBoundArrayCenter; 26 | int maxDxBeforeTruncate = Math.abs(dx) + 1; 27 | blendRadiusBound[i] = Math.sqrt(blendRadiusSq - maxDxBeforeTruncate); 28 | } 29 | 30 | } 31 | 32 | public LinkedBiomeWeightMap getBlendForChunk(long seed, int chunkBaseWorldX, int chunkBaseWorldZ, BiomeEvaluationCallback callback) { 33 | 34 | // Get the list of data points in range. 35 | List> points = gatherer.getPointsFromChunkBase(seed, chunkBaseWorldX, chunkBaseWorldZ); 36 | 37 | // Evaluate and aggregate all biomes to be blended in this chunk. 38 | LinkedBiomeWeightMap linkedBiomeMapStartEntry = null; 39 | for (GatheredPoint point : points) { 40 | 41 | // Get the biome for this data point from the callback. 42 | int biome = callback.getBiomeAt(point.getX(), point.getZ()); 43 | 44 | // Find or create the chunk biome blend weight layer entry for this biome. 45 | LinkedBiomeWeightMap entry = linkedBiomeMapStartEntry; 46 | while (entry != null) { 47 | if (entry.getBiome() == biome) break; 48 | entry = entry.getNext(); 49 | } 50 | if (entry == null) { 51 | entry = linkedBiomeMapStartEntry = 52 | new LinkedBiomeWeightMap(biome, linkedBiomeMapStartEntry); 53 | } 54 | 55 | point.setTag(entry); 56 | } 57 | 58 | // If there is only one biome in range here, we can skip the actual blending step. 59 | if (linkedBiomeMapStartEntry != null && linkedBiomeMapStartEntry.getNext() == null) { 60 | double[] weights = new double[chunkColumnCount]; 61 | linkedBiomeMapStartEntry.setWeights(weights); 62 | for (int i = 0; i < chunkColumnCount; i++) { 63 | weights[i] = 1.0; 64 | } 65 | return linkedBiomeMapStartEntry; 66 | } 67 | 68 | for (LinkedBiomeWeightMap entry = linkedBiomeMapStartEntry; entry != null; entry = entry.getNext()) { 69 | entry.setWeights(new double[chunkColumnCount]); 70 | } 71 | 72 | double z = chunkBaseWorldZ, x = chunkBaseWorldX; 73 | double xStart = x; 74 | double xEnd = xStart + chunkWidthMinusOne; 75 | for (int i = 0; i < chunkColumnCount; i++) { 76 | 77 | // Consider each data point to see if it's inside the radius for this column. 78 | double columnTotalWeight = 0.0; 79 | for (GatheredPoint point : points) { 80 | double dx = x - point.getX(); 81 | double dz = z - point.getZ(); 82 | 83 | double distSq = dx * dx + dz * dz; 84 | 85 | // If it's inside the radius... 86 | if (distSq < blendRadiusSq) { 87 | 88 | // Relative weight = [r^2 - (x^2 + z^2)]^2 89 | double weight = blendRadiusSq - distSq; 90 | weight *= weight; 91 | 92 | point.getTag().getWeights()[i] += weight; 93 | columnTotalWeight += weight; 94 | } 95 | } 96 | 97 | // Normalize so all weights in a column add up to 1. 98 | double inverseTotalWeight = 1.0 / columnTotalWeight; 99 | for (LinkedBiomeWeightMap entry = linkedBiomeMapStartEntry; entry != null; entry = entry.getNext()) { 100 | entry.getWeights()[i] *= inverseTotalWeight; 101 | } 102 | 103 | // A double can fully represent an int, so no precision loss to worry about here. 104 | if (x == xEnd) { 105 | x = xStart; 106 | z++; 107 | } else x++; 108 | } 109 | 110 | return linkedBiomeMapStartEntry; 111 | } 112 | 113 | public static double getInternalMinBlendRadiusForFrequency(double samplingFrequency) { 114 | return UnfilteredPointGatherer.MAX_GRIDSCALE_DISTANCE_TO_CLOSEST_POINT / samplingFrequency; 115 | } 116 | 117 | public double getInternalBlendRadius() { 118 | return blendRadius; 119 | } 120 | 121 | @FunctionalInterface 122 | public static interface BiomeEvaluationCallback { 123 | int getBiomeAt(double x, double z); 124 | } 125 | 126 | private static class BiomeEvaluation { 127 | int biome; 128 | double tempDzSquared; 129 | public BiomeEvaluation(int biome) { 130 | this.biome = biome; 131 | } 132 | } 133 | 134 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/gen/ContinentCache.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.gen; 2 | 3 | import it.unimi.dsi.fastutil.HashCommon; 4 | import net.minecraft.util.math.ChunkPos; 5 | import supercoder79.simplexterrain.api.Heightmap; 6 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 7 | 8 | import java.util.Arrays; 9 | 10 | public class ContinentCache { 11 | private final long[] keys; 12 | private final int[] values; 13 | 14 | private final OpenSimplexNoise noise; 15 | private final int seaLevel; 16 | 17 | public ContinentCache(long seed, int seaLevel) { 18 | this.noise = new OpenSimplexNoise(seed); 19 | this.seaLevel = seaLevel; 20 | 21 | this.keys = new long[2048]; 22 | this.values = new int[2048]; 23 | 24 | Arrays.fill(this.keys, Long.MIN_VALUE); 25 | } 26 | 27 | public int get(int x, int z) { 28 | long key = key(x, z); 29 | int idx = hash(key) & 2047; 30 | 31 | if (this.keys[idx] == key) { 32 | return this.values[idx]; 33 | } 34 | 35 | int height = (int) (this.seaLevel + (noise.sample(x / 1200.0, z / 1200.0) + 0.2) * 16); 36 | this.values[idx] = height; 37 | this.keys[idx] = key; 38 | 39 | return height; 40 | } 41 | 42 | private static int hash(long key) { 43 | return (int) HashCommon.mix(key); 44 | } 45 | 46 | private static long key(int x, int z) { 47 | return ChunkPos.toLong(x, z); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/gen/ContinentGenerator.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.gen; 2 | 3 | import supercoder79.simplexterrain.api.Heightmap; 4 | 5 | public class ContinentGenerator implements Heightmap { 6 | private final ThreadLocal cache; 7 | 8 | public ContinentGenerator(long seed, int seaLevel) { 9 | this.cache = ThreadLocal.withInitial(() -> new ContinentCache(seed, seaLevel)); 10 | } 11 | 12 | @Override 13 | public int getHeight(int x, int z) { 14 | return this.cache.get().get(x, z); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/gen/SimplexBiomeSource.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.gen; 2 | 3 | import com.mojang.serialization.Codec; 4 | import com.mojang.serialization.codecs.RecordCodecBuilder; 5 | import net.minecraft.util.registry.Registry; 6 | import net.minecraft.util.registry.RegistryKey; 7 | import net.minecraft.util.registry.RegistryLookupCodec; 8 | import net.minecraft.world.biome.Biome; 9 | import net.minecraft.world.biome.BiomeKeys; 10 | import net.minecraft.world.biome.BuiltinBiomes; 11 | import net.minecraft.world.biome.source.BiomeLayerSampler; 12 | import net.minecraft.world.biome.source.BiomeSource; 13 | import net.minecraft.world.biome.source.VanillaLayeredBiomeSource; 14 | import net.minecraft.world.gen.ChunkRandom; 15 | import supercoder79.simplexterrain.SimplexTerrain; 16 | import supercoder79.simplexterrain.api.BackingBiomeSource; 17 | import supercoder79.simplexterrain.api.Heightmap; 18 | import supercoder79.simplexterrain.world.BiomeData; 19 | import supercoder79.simplexterrain.world.biomelayers.SimplexBiomeLayers; 20 | import supercoder79.simplexterrain.world.noisetype.NoiseType; 21 | import supercoder79.simplexterrain.world.noisetype.NoiseTypeHolder; 22 | 23 | public class SimplexBiomeSource extends BiomeSource implements BackingBiomeSource { 24 | public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( 25 | RegistryLookupCodec.of(Registry.BIOME_KEY).forGetter(source -> source.biomeRegistry), 26 | Codec.LONG.fieldOf("seed").stable().forGetter(source -> source.seed)) 27 | .apply(instance, instance.stable(SimplexBiomeSource::new))); 28 | 29 | private final BiomeLayerSampler backingSampler; 30 | 31 | private final Registry biomeRegistry; 32 | private final long seed; 33 | 34 | private Heightmap heightmap = Heightmap.NONE; 35 | private Heightmap continent = Heightmap.NONE; 36 | 37 | public SimplexBiomeSource(Registry biomeRegistry, long seed) { 38 | super(VanillaLayeredBiomeSource.BIOMES.stream().map((registryKey) -> () -> (Biome)biomeRegistry.getOrThrow(registryKey))); 39 | this.biomeRegistry = biomeRegistry; 40 | this.seed = seed; 41 | 42 | this.backingSampler = SimplexBiomeLayers.build(biomeRegistry, seed); 43 | NoiseTypeHolder.initialize(new ChunkRandom(seed)); 44 | } 45 | 46 | public void setHeightmap(Heightmap heightmap) { 47 | this.heightmap = heightmap; 48 | } 49 | 50 | public void setContinentHeightmap(Heightmap heightmap) { 51 | this.continent = heightmap; 52 | } 53 | 54 | @Override 55 | public Biome getBiomeForNoiseGen(int x, int y, int z) { 56 | if (heightmap == null) return BuiltinBiomes.PLAINS; 57 | Biome biome = getBiomeAt(x, z, heightmap.getBiomeData(x, z)); 58 | return biome == null ? BuiltinBiomes.PLAINS : biome; 59 | } 60 | 61 | public Biome getBiomeAt(int x, int z, BiomeData data) { 62 | int height = data.getHeight(); 63 | 64 | int continent = this.continent.getHeight(x << 2, z << 2); 65 | 66 | if (continent < SimplexTerrain.CONFIG.seaLevel) { 67 | return this.biomeRegistry.get(BiomeKeys.OCEAN); 68 | } 69 | 70 | RegistryKey key = this.biomeRegistry.getKey(this.backingSampler.sample(this.biomeRegistry, x << 2, z << 2)).get(); 71 | 72 | NoiseType type = NoiseTypeHolder.get(key).get(x << 2, z << 2); 73 | 74 | // TODO: provide a better way of doing this 75 | int y = (int) type.modify(x << 2, z << 2, 0, 1, new BiomeData()); 76 | 77 | return this.biomeRegistry.get(type.modifyBiome(y, key)); 78 | } 79 | 80 | @Override 81 | protected Codec getCodec() { 82 | return CODEC; 83 | } 84 | 85 | @Override 86 | public BiomeSource withSeed(long l) { 87 | return new SimplexBiomeSource(this.biomeRegistry, l); 88 | } 89 | 90 | @Override 91 | public RegistryKey getBacking(int x, int z) { 92 | return this.biomeRegistry.getKey(this.backingSampler.sample(this.biomeRegistry, x, z)).get(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/gen/SimplexNetherGeneration.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.gen; 2 | 3 | import net.minecraft.block.Blocks; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraft.world.WorldAccess; 6 | import net.minecraft.world.biome.Biome; 7 | import net.minecraft.world.biome.source.BiomeSource; 8 | import net.minecraft.world.chunk.Chunk; 9 | import supercoder79.simplexterrain.noise.gradient.SimplexStyleNoise; 10 | 11 | public class SimplexNetherGeneration { 12 | 13 | private static SimplexStyleNoise mainNoise; 14 | private static SimplexStyleNoise detailsNoise; 15 | 16 | public static void init(long seed) { 17 | mainNoise = new SimplexStyleNoise(seed + 12); 18 | detailsNoise = new SimplexStyleNoise(seed + 20); 19 | } 20 | 21 | public static void generate(WorldAccess world, Chunk chunk, BiomeSource biomeSource, int seaLevel) { 22 | //TODO: threading 23 | 24 | BlockPos.Mutable mutable = new BlockPos.Mutable(); 25 | 26 | for (int x = 0; x < 16; x++) { 27 | mutable.setX(x); 28 | 29 | for (int z = 0; z < 16; z++) { 30 | mutable.setZ(z); 31 | 32 | double depth = 0; 33 | double scale = 0; 34 | 35 | for (int x1 = -1; x1 <= 1; x1++) { 36 | for (int z1 = -1; z1 <= 1; z1++) { 37 | Biome biome = biomeSource.getBiomeForNoiseGen((chunk.getPos().x*16) + (x + x1), 32, (chunk.getPos().z*16) + (z + z1)); 38 | 39 | depth += biome.getDepth(); 40 | scale += biome.getScale(); 41 | } 42 | } 43 | 44 | depth /= 9; 45 | scale /= 9; 46 | 47 | for (int y = 0; y < 127; y++) { 48 | mutable.setY(y); 49 | if (getNoiseAt(depth, scale, (chunk.getPos().x*16) + x, y, (chunk.getPos().z*16) + z) > 0) { 50 | chunk.setBlockState(mutable, Blocks.NETHERRACK.getDefaultState(), false); 51 | } else if (y < seaLevel) { 52 | chunk.setBlockState(mutable, Blocks.LAVA.getDefaultState(), false); 53 | } 54 | } 55 | } 56 | } 57 | } 58 | 59 | private static double getNoiseAt(double depth, double scale, int x, int y, int z) { 60 | double noise = mainNoise.sample(x / 80.0, y / 60.0, z / 80.0) * (1 + depth); 61 | noise += detailsNoise.sample(x / 24.0, y / 18.0, z / 24.0) * 0.125; 62 | 63 | noise /= (1 - scale); 64 | 65 | noise += Math.max((22.0 / y) - 1, 0); // lower bound 66 | noise += Math.max((-22.0 / (y - 130)) - 1, 0); // upper bound 67 | 68 | return noise; 69 | } 70 | } -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisemodifier/DetailNoiseModifier.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisemodifier; 2 | 3 | import net.minecraft.world.gen.ChunkRandom; 4 | import supercoder79.simplexterrain.SimplexTerrain; 5 | import supercoder79.simplexterrain.api.noise.Noise; 6 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 7 | import supercoder79.simplexterrain.api.noisemodifier.NoiseModifier; 8 | import supercoder79.simplexterrain.configs.ConfigHelper; 9 | import supercoder79.simplexterrain.configs.noisemodifiers.DetailsConfigData; 10 | import supercoder79.simplexterrain.world.BiomeData; 11 | 12 | import java.nio.file.Paths; 13 | 14 | public class DetailNoiseModifier implements NoiseModifier { 15 | private DetailsConfigData config; 16 | private OctaveNoiseSampler detailNoise; 17 | 18 | @Override 19 | public void init(long seed) { 20 | detailNoise = new OctaveNoiseSampler<>(SimplexTerrain.CONFIG.noiseGenerator.noiseClass, new ChunkRandom(seed), config.octaves, config.frequency, config.amplitudeHigh, config.amplitudeLow); 21 | } 22 | 23 | @Override 24 | public void setup() { 25 | config = ConfigHelper.getFromConfig(DetailsConfigData.class, Paths.get("config", "simplexterrain", "noisemodifiers", "details.json")); 26 | } 27 | 28 | @Override 29 | public double modify(int x, int z, double currentNoiseValue, BiomeData data) { 30 | return currentNoiseValue + detailNoise.sample(x, z); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisemodifier/MountainsNoiseModifier.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisemodifier; 2 | 3 | import net.minecraft.world.gen.ChunkRandom; 4 | import supercoder79.simplexterrain.SimplexTerrain; 5 | import supercoder79.simplexterrain.api.noise.Noise; 6 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 7 | import supercoder79.simplexterrain.api.noisemodifier.NoiseModifier; 8 | import supercoder79.simplexterrain.configs.ConfigHelper; 9 | import supercoder79.simplexterrain.configs.noisemodifiers.MountainConfigData; 10 | import supercoder79.simplexterrain.world.BiomeData; 11 | 12 | import java.nio.file.Paths; 13 | 14 | public class MountainsNoiseModifier implements NoiseModifier { 15 | private MountainConfigData config; 16 | private OctaveNoiseSampler mountainNoise; 17 | 18 | @Override 19 | public void init(long seed) { 20 | mountainNoise = new OctaveNoiseSampler<>(SimplexTerrain.CONFIG.noiseGenerator.noiseClass, new ChunkRandom(seed + 20), config.octaves, config.frequency, config.amplitudeHigh, config.amplitudeLow); 21 | } 22 | 23 | @Override 24 | public void setup() { 25 | config = ConfigHelper.getFromConfig(MountainConfigData.class, Paths.get("config", "simplexterrain", "noisemodifiers", "mountains.json")); 26 | } 27 | 28 | @Override 29 | public double modify(int x, int z, double currentNoiseValue, BiomeData data) { 30 | return currentNoiseValue + Math.max(mountainNoise.sample(x, z), 0); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisemodifier/MushroomIslandsNoiseModifier.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisemodifier; 2 | 3 | import net.minecraft.util.math.MathHelper; 4 | import supercoder79.simplexterrain.SimplexTerrain; 5 | import supercoder79.simplexterrain.api.noise.Noise; 6 | import supercoder79.simplexterrain.api.noisemodifier.NoiseModifier; 7 | import supercoder79.simplexterrain.configs.ConfigHelper; 8 | import supercoder79.simplexterrain.configs.noisemodifiers.MushroomFieldsConfigData; 9 | import supercoder79.simplexterrain.noise.NoiseMath; 10 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 11 | import supercoder79.simplexterrain.world.BiomeData; 12 | 13 | import java.nio.file.Paths; 14 | 15 | public class MushroomIslandsNoiseModifier implements NoiseModifier { 16 | private Noise maskNoise; 17 | private MushroomFieldsConfigData config; 18 | 19 | @Override 20 | public void init(long seed) { 21 | this.maskNoise = new OpenSimplexNoise(seed - 146); 22 | } 23 | 24 | @Override 25 | public void setup() { 26 | config = ConfigHelper.getFromConfig(MushroomFieldsConfigData.class, Paths.get("config", "simplexterrain", "noisemodifiers", "mushroom_islands.json")); 27 | } 28 | 29 | @Override 30 | public double modify(int x, int z, double currentNoiseValue, BiomeData data) { 31 | double mNoise = maskNoise.sample(x / config.scale, z / config.scale); 32 | if (mNoise > config.threshold) { 33 | double ndelta = (mNoise - config.threshold) * 50; 34 | double add = MathHelper.clampedLerp(0, config.height, ndelta); 35 | double delta = (SimplexTerrain.CONFIG.seaLevel - 15) - NoiseMath.sigmoid(currentNoiseValue); 36 | 37 | if (delta > 0) { 38 | double end = MathHelper.clampedLerp(0, add, delta / 1.5); 39 | 40 | currentNoiseValue += end; 41 | data.setMushroomIsland(); 42 | } 43 | } 44 | 45 | return currentNoiseValue; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisemodifier/NoiseModifiers.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisemodifier; 2 | 3 | import supercoder79.simplexterrain.api.noisemodifier.NoiseModifier; 4 | 5 | public enum NoiseModifiers { 6 | MOUNTAINS(new MountainsNoiseModifier()), 7 | RIDGES(new RidgesNoiseModifier()), 8 | DETAILS(new DetailNoiseModifier()), 9 | PLATEAUS(new PlateausNoiseModifier()), 10 | RIVERS(new RiversNoiseModifier()), 11 | MUSHROOM_ISLANDS(new MushroomIslandsNoiseModifier()); 12 | 13 | public NoiseModifier noiseModifier; 14 | 15 | NoiseModifiers(NoiseModifier noiseModifier) { 16 | this.noiseModifier = noiseModifier; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisemodifier/PlateausNoiseModifier.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisemodifier; 2 | 3 | import net.minecraft.util.math.MathHelper; 4 | import net.minecraft.world.gen.ChunkRandom; 5 | import supercoder79.simplexterrain.SimplexTerrain; 6 | import supercoder79.simplexterrain.api.noise.Noise; 7 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 8 | import supercoder79.simplexterrain.api.noisemodifier.NoiseModifier; 9 | import supercoder79.simplexterrain.configs.ConfigHelper; 10 | import supercoder79.simplexterrain.configs.noisemodifiers.PlateausConfigData; 11 | import supercoder79.simplexterrain.world.BiomeData; 12 | 13 | import java.nio.file.Paths; 14 | 15 | public class PlateausNoiseModifier implements NoiseModifier { 16 | private PlateausConfigData config; 17 | private OctaveNoiseSampler plateauNoise; 18 | 19 | @Override 20 | public void init(long seed) { 21 | plateauNoise = new OctaveNoiseSampler<>(SimplexTerrain.CONFIG.noiseGenerator.noiseClass, new ChunkRandom(seed + 3), config.octaves, config.frequency, 1, 1); 22 | } 23 | 24 | @Override 25 | public void setup() { 26 | config = ConfigHelper.getFromConfig(PlateausConfigData.class, Paths.get("config", "simplexterrain", "noisemodifiers", "plateaus.json")); 27 | } 28 | 29 | @Override 30 | public double modify(int x, int z, double currentNoiseValue, BiomeData data) { 31 | double noise = plateauNoise.sample(x, z); 32 | 33 | if (noise > config.threshold) { 34 | currentNoiseValue += MathHelper.lerp(fade(noise, config.threshold, config.interpolation), 0, config.height); 35 | } 36 | 37 | return currentNoiseValue; 38 | } 39 | 40 | private static double fade(double noise, double threshold, double interpolation) { 41 | double fade = (threshold + interpolation) - noise; 42 | // Create a smooth interpolation 43 | if (fade > 0) { 44 | fade = Math.abs(fade); 45 | fade /= interpolation; 46 | fade = smoothstep(1 - fade); 47 | } else { 48 | // This is to make the rest of the plateau flat-ish (outside of the interpolation region) 49 | fade = 1; 50 | } 51 | 52 | return fade; 53 | } 54 | 55 | private static double smoothstep(double d) { 56 | return d * d * (3 - 2 * d); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisemodifier/RidgesNoiseModifier.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisemodifier; 2 | 3 | import net.minecraft.world.gen.ChunkRandom; 4 | import supercoder79.simplexterrain.SimplexTerrain; 5 | import supercoder79.simplexterrain.api.noise.Noise; 6 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 7 | import supercoder79.simplexterrain.api.noisemodifier.NoiseModifier; 8 | import supercoder79.simplexterrain.configs.ConfigHelper; 9 | import supercoder79.simplexterrain.configs.noisemodifiers.RidgesConfigData; 10 | import supercoder79.simplexterrain.world.BiomeData; 11 | 12 | import java.nio.file.Paths; 13 | 14 | public class RidgesNoiseModifier implements NoiseModifier { 15 | private RidgesConfigData config; 16 | private OctaveNoiseSampler ridgedNoise; 17 | 18 | @Override 19 | public void init(long seed) { 20 | ridgedNoise = new OctaveNoiseSampler<>(SimplexTerrain.CONFIG.noiseGenerator.noiseClass, new ChunkRandom(seed - 20), config.octaves, config.frequency, 1, 1); 21 | } 22 | 23 | @Override 24 | public void setup() { 25 | config = ConfigHelper.getFromConfig(RidgesConfigData.class, Paths.get("config", "simplexterrain", "noisemodifiers", "ridges.json")); 26 | } 27 | 28 | @Override 29 | public double modify(int x, int z, double currentNoiseValue, BiomeData data) { 30 | return currentNoiseValue + ((1 - Math.abs(ridgedNoise.sample(x, z))) * config.amplitude); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisemodifier/RiversNoiseModifier.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisemodifier; 2 | 3 | import net.minecraft.util.math.MathHelper; 4 | import supercoder79.simplexterrain.SimplexTerrain; 5 | import supercoder79.simplexterrain.api.noise.Noise; 6 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 7 | import supercoder79.simplexterrain.api.noisemodifier.NoiseModifier; 8 | import supercoder79.simplexterrain.configs.ConfigHelper; 9 | import supercoder79.simplexterrain.configs.noisemodifiers.RiversConfigData; 10 | import supercoder79.simplexterrain.noise.NoiseMath; 11 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 12 | import supercoder79.simplexterrain.world.BiomeData; 13 | 14 | import java.nio.file.Paths; 15 | import java.util.Random; 16 | 17 | public class RiversNoiseModifier implements NoiseModifier { 18 | public RiversConfigData config; 19 | private Noise noise; 20 | private Noise detailNoise; 21 | private Noise depthNoise; 22 | private Noise sizeNoise; 23 | 24 | @Override 25 | public void init(long seed) { 26 | noise = new OpenSimplexNoise(seed - 43); 27 | detailNoise = new OpenSimplexNoise(seed + 43); 28 | depthNoise = new OctaveNoiseSampler<>(OpenSimplexNoise.class, new Random(seed + 32), 3, config.scale / 2.0, 2.5, 6); 29 | sizeNoise = new OpenSimplexNoise(seed + 53); 30 | } 31 | 32 | @Override 33 | public void setup() { 34 | config = ConfigHelper.getFromConfig(RiversConfigData.class, Paths.get("config", "simplexterrain", "noisemodifiers", "rivers.json")); 35 | } 36 | 37 | @Override 38 | public double modify(int x, int z, double currentNoiseValue, BiomeData data) { 39 | double noise = this.noise.sample(x / config.scale, z / config.scale) + (detailNoise.sample(x / config.scale * 5.0, z / config.scale * 5.0) * 0.2); 40 | 41 | 42 | double depth = config.depth + depthNoise.sample(x, z); 43 | double size = config.size + (sizeNoise.sample(x / config.scale * 3.0, z / config.scale * 3.0) * 0.025); 44 | 45 | if (currentNoiseValue > depth) { 46 | if (noise < size && noise > -size) { 47 | // Interpolate downwards 48 | currentNoiseValue = MathHelper.lerp(smoothstep(noise / size), currentNoiseValue, depth); 49 | 50 | double realY = NoiseMath.sigmoid(currentNoiseValue); 51 | 52 | // Place a river if we're less than sea level, otherwise force place lowlands to prevent beach gen 53 | if (realY < SimplexTerrain.CONFIG.seaLevel) { 54 | data.setRiver(); 55 | } else if (realY <= SimplexTerrain.CONFIG.seaLevel + 9) { 56 | data.setForcedLowlands(); 57 | } 58 | } 59 | } 60 | 61 | return currentNoiseValue; 62 | } 63 | public static double smoothstep(double t) { 64 | return (1 - t * t) * (1 - t * t) * (1 - t * t); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/DefaultNoiseType.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype; 2 | 3 | import net.minecraft.world.gen.ChunkRandom; 4 | import supercoder79.simplexterrain.world.BiomeData; 5 | 6 | public class DefaultNoiseType implements NoiseType { 7 | public static final DefaultNoiseType INSTANCE = new DefaultNoiseType(); 8 | 9 | @Override 10 | public void init(ChunkRandom random) { 11 | 12 | } 13 | 14 | @Override 15 | public double modify(int x, int z, double currentNoiseValue, double weight, BiomeData data) { 16 | return 0; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/NoiseType.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype; 2 | 3 | import net.minecraft.util.math.Vec3d; 4 | import net.minecraft.util.registry.RegistryKey; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.gen.ChunkRandom; 7 | import supercoder79.simplexterrain.world.BiomeData; 8 | 9 | import java.util.Map; 10 | 11 | public interface NoiseType { 12 | void init(ChunkRandom random); 13 | 14 | double modify(int x, int z, double currentNoiseValue, double weight, BiomeData data); 15 | 16 | default RegistryKey modifyBiome(int y, RegistryKey existing) { 17 | return existing; 18 | } 19 | 20 | default void addToPicker(Map points, double theta) { 21 | points.put(new Vec3d(Math.cos(theta) * Math.sqrt(2), 0, Math.sin(theta) * Math.sqrt(2)), this); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/NoiseTypeCache.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype; 2 | 3 | import it.unimi.dsi.fastutil.HashCommon; 4 | import net.minecraft.util.math.ChunkPos; 5 | 6 | import java.util.Arrays; 7 | 8 | public class NoiseTypeCache { 9 | private final NoiseTypePicker picker; 10 | private final ThreadLocal cache; 11 | 12 | public NoiseTypeCache(NoiseTypePicker picker) { 13 | this.picker = picker; 14 | this.cache = ThreadLocal.withInitial(() -> new Cache(this.picker)); 15 | } 16 | 17 | public NoiseTypePicker getPicker() { 18 | return picker; 19 | } 20 | 21 | public NoiseType get(int x, int z) { 22 | return this.cache.get().get(x, z); 23 | } 24 | 25 | private static class Cache { 26 | private final long[] keys; 27 | private final NoiseType[] values; 28 | private final NoiseTypePicker picker; 29 | 30 | private Cache(NoiseTypePicker picker) { 31 | this.picker = picker; 32 | this.keys = new long[2048]; 33 | this.values = new NoiseType[2048]; 34 | 35 | Arrays.fill(this.keys, Long.MIN_VALUE); 36 | } 37 | 38 | public NoiseType get(int x, int z) { 39 | long key = key(x, z); 40 | int idx = hash(key) & 2047; 41 | 42 | if (this.keys[idx] == key) { 43 | return this.values[idx]; 44 | } 45 | 46 | NoiseType type = this.picker.get(x, z); 47 | this.values[idx] = type; 48 | this.keys[idx] = key; 49 | 50 | return type; 51 | } 52 | 53 | private static int hash(long key) { 54 | return (int) HashCommon.mix(key); 55 | } 56 | 57 | private static long key(int x, int z) { 58 | return ChunkPos.toLong(x, z); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/NoiseTypeHolder.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype; 2 | 3 | import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; 4 | import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; 5 | import net.minecraft.util.registry.Registry; 6 | import net.minecraft.util.registry.RegistryKey; 7 | import net.minecraft.world.biome.Biome; 8 | import net.minecraft.world.gen.ChunkRandom; 9 | 10 | import java.util.HashMap; 11 | import java.util.LinkedHashMap; 12 | import java.util.Map; 13 | import java.util.function.Function; 14 | 15 | public class NoiseTypeHolder { 16 | public static final Map, Function> BIOME_FACTORIES = new LinkedHashMap<>(); 17 | public static final Map IDS = new Reference2IntOpenHashMap<>(); 18 | public static final Map IDS_REVERSE = new Int2ReferenceOpenHashMap<>(); 19 | public static int currentId = 0; // TODO: remove ugly shared state 20 | 21 | private static final Map, NoiseTypeCache> FOR_BIOME = new LinkedHashMap<>(); 22 | 23 | public static void initialize(ChunkRandom random) { 24 | FOR_BIOME.clear(); 25 | IDS.clear(); 26 | currentId = 0; 27 | 28 | for (Map.Entry, Function> entry : BIOME_FACTORIES.entrySet()) { 29 | FOR_BIOME.put(entry.getKey(), entry.getValue().apply(random)); 30 | } 31 | } 32 | 33 | public static NoiseTypeCache get(RegistryKey biome) { 34 | return FOR_BIOME.get(biome); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/NoiseTypePicker.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype; 2 | 3 | import net.minecraft.util.math.Vec3d; 4 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 5 | 6 | import java.util.*; 7 | 8 | public class NoiseTypePicker { 9 | private final OpenSimplexNoise noise1; 10 | private final OpenSimplexNoise noise2; 11 | private final OpenSimplexNoise noise3; 12 | private final OpenSimplexNoise noise1a; 13 | private final OpenSimplexNoise noise3a; 14 | private final Map points; 15 | 16 | public NoiseTypePicker(Random random, List types) { 17 | this.noise1 = new OpenSimplexNoise(random.nextLong()); 18 | this.noise2 = new OpenSimplexNoise(random.nextLong()); 19 | this.noise3 = new OpenSimplexNoise(random.nextLong()); 20 | this.noise1a = new OpenSimplexNoise(random.nextLong()); 21 | this.noise3a = new OpenSimplexNoise(random.nextLong()); 22 | 23 | 24 | Map points = new HashMap<>(); 25 | for (int i = 0; i < types.size(); i++) { 26 | // Add to registry 27 | NoiseTypeHolder.IDS.put(types.get(i), NoiseTypeHolder.currentId); 28 | NoiseTypeHolder.IDS_REVERSE.put(NoiseTypeHolder.currentId, types.get(i)); 29 | NoiseTypeHolder.currentId++; 30 | 31 | double theta = (i / (double)types.size()) * Math.PI * 2; 32 | types.get(i).addToPicker(points, theta); 33 | } 34 | 35 | this.points = points; 36 | } 37 | 38 | public Map getPoints() { 39 | return points; 40 | } 41 | 42 | public NoiseType get(int x, int z) { 43 | double ax = this.noise1.sample( x / 600.0, z / 600.0) + (this.noise1a.sample(x / 200.0, z / 200.0) * 0.333); 44 | double ay = this.noise2.sample( x / 600.0, z / 600.0); 45 | double az = this.noise3.sample(x / 600.0, z / 600.0) + (this.noise3a.sample(x / 200.0, z / 200.0) * 0.333); 46 | 47 | Vec3d vec = new Vec3d(ax, ay, az); 48 | double minimumDist = Double.MAX_VALUE; 49 | NoiseType closest = DefaultNoiseType.INSTANCE; 50 | 51 | for (Map.Entry type : this.points.entrySet()) { 52 | double dist = type.getKey().squaredDistanceTo(vec); 53 | if (dist < minimumDist) { 54 | minimumDist = dist; 55 | closest = type.getValue(); 56 | } 57 | } 58 | 59 | return closest; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/desert/DunesNoiseType.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype.desert; 2 | 3 | import net.minecraft.world.gen.ChunkRandom; 4 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 5 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 6 | import supercoder79.simplexterrain.world.BiomeData; 7 | import supercoder79.simplexterrain.world.noisetype.NoiseType; 8 | 9 | public class DunesNoiseType implements NoiseType { 10 | private OpenSimplexNoise ridged; 11 | private OctaveNoiseSampler noise; 12 | 13 | @Override 14 | public void init(ChunkRandom random) { 15 | this.ridged = new OpenSimplexNoise(random.nextLong()); 16 | this.noise = new OctaveNoiseSampler<>(OpenSimplexNoise.class, random, 2, 300, 20, 10); 17 | } 18 | 19 | @Override 20 | public double modify(int x, int z, double currentNoiseValue, double weight, BiomeData data) { 21 | double ridgedNoise = (1 - Math.abs(this.ridged.sample(x / 120.0, z / 120.0))) * 20 * weight; 22 | 23 | return ridgedNoise + this.noise.sample(x, z) * weight; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/desert/SavannaHillsNoiseType.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype.desert; 2 | 3 | import net.minecraft.util.math.MathHelper; 4 | import net.minecraft.util.registry.RegistryKey; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.biome.BiomeKeys; 7 | import net.minecraft.world.gen.ChunkRandom; 8 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 9 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 10 | import supercoder79.simplexterrain.world.BiomeData; 11 | import supercoder79.simplexterrain.world.noisetype.NoiseType; 12 | 13 | public class SavannaHillsNoiseType implements NoiseType { 14 | private OctaveNoiseSampler noise; 15 | private OpenSimplexNoise ridged; 16 | 17 | @Override 18 | public void init(ChunkRandom random) { 19 | this.noise = new OctaveNoiseSampler<>(OpenSimplexNoise.class, random, 3, 220, 30, 16); 20 | this.ridged = new OpenSimplexNoise(random.nextLong()); 21 | } 22 | 23 | @Override 24 | public double modify(int x, int z, double currentNoiseValue, double weight, BiomeData data) { 25 | double ridgedNoise = Math.abs(1 - this.ridged.sample(x / 100.0, z / 100.0)) * 12 * weight; 26 | double addition = MathHelper.lerp(MathHelper.perlinFade(weight), 0, 10); 27 | double noise = this.noise.sample(x, z) * weight; 28 | 29 | return addition + noise + ridgedNoise; 30 | } 31 | 32 | @Override 33 | public RegistryKey modifyBiome(int y, RegistryKey existing) { 34 | return y > (85 - 61) ? BiomeKeys.SAVANNA : existing; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/forest/HillsNoiseType.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype.forest; 2 | 3 | import net.minecraft.world.gen.ChunkRandom; 4 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 5 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 6 | import supercoder79.simplexterrain.world.BiomeData; 7 | import supercoder79.simplexterrain.world.noisetype.NoiseType; 8 | 9 | public class HillsNoiseType implements NoiseType { 10 | private OctaveNoiseSampler noise; 11 | 12 | @Override 13 | public void init(ChunkRandom random) { 14 | this.noise = new OctaveNoiseSampler<>(OpenSimplexNoise.class, random, 3, 120, 20, 12); 15 | } 16 | 17 | @Override 18 | public double modify(int x, int z, double currentNoiseValue, double weight, BiomeData data) { 19 | return (8 + noise.sample(x, z)) * weight; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/plains/ForestedHillsNoiseType.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype.plains; 2 | 3 | import net.minecraft.util.math.MathHelper; 4 | import net.minecraft.util.registry.RegistryKey; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.biome.BiomeKeys; 7 | import net.minecraft.world.gen.ChunkRandom; 8 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 9 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 10 | import supercoder79.simplexterrain.world.BiomeData; 11 | import supercoder79.simplexterrain.world.noisetype.NoiseType; 12 | 13 | public class ForestedHillsNoiseType implements NoiseType { 14 | private OctaveNoiseSampler noise; 15 | private OpenSimplexNoise ridged; 16 | 17 | @Override 18 | public void init(ChunkRandom random) { 19 | this.noise = new OctaveNoiseSampler<>(OpenSimplexNoise.class, random, 4, 160, 30, 16); 20 | this.ridged = new OpenSimplexNoise(random.nextLong()); 21 | } 22 | 23 | @Override 24 | public double modify(int x, int z, double currentNoiseValue, double weight, BiomeData data) { 25 | double ridgedNoise = Math.abs(1 - this.ridged.sample(x / 60.0, z / 60.0)) * 12 * weight; 26 | double addition = MathHelper.lerp(MathHelper.perlinFade(weight), 0, 10); 27 | double noise = this.noise.sample(x, z) * weight; 28 | 29 | return addition + noise + ridgedNoise; 30 | } 31 | 32 | @Override 33 | public RegistryKey modifyBiome(int y, RegistryKey existing) { 34 | return y > (85 - 61) ? BiomeKeys.FOREST : existing; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/plains/LowLyingPlainsNoiseType.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype.plains; 2 | 3 | import net.minecraft.util.math.Vec3d; 4 | import net.minecraft.world.gen.ChunkRandom; 5 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 6 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 7 | import supercoder79.simplexterrain.world.BiomeData; 8 | import supercoder79.simplexterrain.world.noisetype.NoiseType; 9 | 10 | import java.util.Map; 11 | 12 | public class LowLyingPlainsNoiseType implements NoiseType { 13 | private OctaveNoiseSampler noise; 14 | 15 | @Override 16 | public void init(ChunkRandom random) { 17 | this.noise = new OctaveNoiseSampler<>(OpenSimplexNoise.class, random, 4, 100, 8, 4); 18 | } 19 | 20 | @Override 21 | public double modify(int x, int z, double currentNoiseValue, double weight, BiomeData data) { 22 | return -1 + this.noise.sample(x, z); 23 | } 24 | 25 | @Override 26 | public void addToPicker(Map points, double theta) { 27 | points.put(new Vec3d(Math.cos(theta) * Math.sqrt(3), 0, Math.sin(theta) * Math.sqrt(3)), this); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/plains/MountainsNoiseType.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype.plains; 2 | 3 | import net.minecraft.util.math.MathHelper; 4 | import net.minecraft.util.registry.RegistryKey; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.biome.BiomeKeys; 7 | import net.minecraft.world.gen.ChunkRandom; 8 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 9 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 10 | import supercoder79.simplexterrain.world.BiomeData; 11 | import supercoder79.simplexterrain.world.noisetype.NoiseType; 12 | 13 | public class MountainsNoiseType implements NoiseType { 14 | private OctaveNoiseSampler noise; 15 | private OctaveNoiseSampler noise2; 16 | private OpenSimplexNoise ridged; 17 | 18 | @Override 19 | public void init(ChunkRandom random) { 20 | this.noise = new OctaveNoiseSampler<>(OpenSimplexNoise.class, random, 4, 160, 40, 20); 21 | this.noise2 = new OctaveNoiseSampler<>(OpenSimplexNoise.class, random, 2, 600, 20, 20); 22 | this.ridged = new OpenSimplexNoise(random.nextLong()); 23 | } 24 | 25 | @Override 26 | public double modify(int x, int z, double currentNoiseValue, double weight, BiomeData data) { 27 | double ridgedNoise = Math.abs(1 - this.ridged.sample(x / 120.0, z / 120.0)) * 20 * weight; 28 | double addition = MathHelper.lerp(MathHelper.perlinFade(weight), 0, 20); 29 | double noise = this.noise.sample(x, z) * weight; 30 | noise += this.noise2.sample(x, z) * weight; 31 | 32 | return 3 + addition + noise + ridgedNoise; 33 | } 34 | 35 | @Override 36 | public RegistryKey modifyBiome(int y, RegistryKey existing) { 37 | if (y > 100 - 61) { 38 | return BiomeKeys.TAIGA; 39 | } 40 | 41 | return y > (85 - 61) ? BiomeKeys.FOREST : existing; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/noisetype/plains/PlainsNoiseType.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.noisetype.plains; 2 | 3 | import net.minecraft.world.gen.ChunkRandom; 4 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 5 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 6 | import supercoder79.simplexterrain.world.BiomeData; 7 | import supercoder79.simplexterrain.world.noisetype.NoiseType; 8 | 9 | public class PlainsNoiseType implements NoiseType { 10 | private OctaveNoiseSampler noise; 11 | @Override 12 | public void init(ChunkRandom random) { 13 | this.noise = new OctaveNoiseSampler<>(OpenSimplexNoise.class, random, 4, 140, 12, 12); 14 | } 15 | 16 | @Override 17 | public double modify(int x, int z, double currentNoiseValue, double weight, BiomeData data) { 18 | return 5 + this.noise.sample(x, z); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/postprocessor/ErosionPostProcessor.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.postprocessor; 2 | 3 | import java.nio.file.Paths; 4 | import java.util.Random; 5 | 6 | import net.minecraft.block.Blocks; 7 | import net.minecraft.util.math.BlockPos; 8 | import net.minecraft.util.math.ChunkPos; 9 | import net.minecraft.world.WorldAccess; 10 | import net.minecraft.world.gen.ChunkRandom; 11 | import supercoder79.simplexterrain.SimplexTerrain; 12 | import supercoder79.simplexterrain.api.Heightmap; 13 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 14 | import supercoder79.simplexterrain.api.postprocess.TerrainPostProcessor; 15 | import supercoder79.simplexterrain.configs.ConfigHelper; 16 | import supercoder79.simplexterrain.configs.postprocessors.ErosionConfigData; 17 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 18 | 19 | public class ErosionPostProcessor implements TerrainPostProcessor { 20 | private ErosionConfigData config; 21 | private OctaveNoiseSampler sampler; 22 | 23 | @Override 24 | public void init(long seed) { 25 | sampler = new OctaveNoiseSampler<>(OpenSimplexNoise.class, new ChunkRandom(seed), config.octaves, config.frequency, config.amplitudeHigh, config.amplitudeLow); 26 | } 27 | 28 | @Override 29 | public void setup() { 30 | config = ConfigHelper.getFromConfig(ErosionConfigData.class, Paths.get("config", "simplexterrain", "postprocessors", "erosion.json")); 31 | } 32 | 33 | @Override 34 | public void process(WorldAccess world, Random rand, int chunkX, int chunkZ, Heightmap heightmap) { 35 | int[] heights = heightmap.getHeightsInChunk(new ChunkPos(chunkX, chunkZ)); 36 | BlockPos.Mutable mutable = new BlockPos.Mutable(); 37 | for (int x = 0; x < 16; x++) { 38 | mutable.setX(chunkX*16 + x); 39 | for (int z = 0; z < 16; z++) { 40 | mutable.setZ(chunkZ*16 + z); 41 | double sample = sampler.sample(chunkX*16 + x, chunkZ*16 + z) + config.baseNoise; 42 | if (sample < config.threshold && heights[x*16 + z] > SimplexTerrain.CONFIG.seaLevel) { 43 | for (int y = 0; y < Math.abs(sample); y++) { 44 | mutable.setY(heights[x*16 + z] - y); 45 | world.setBlockState(mutable, Blocks.AIR.getDefaultState(), 2); 46 | } 47 | if (world.getBlockState(mutable.down()) == Blocks.DIRT.getDefaultState()) world.setBlockState(mutable.down(), Blocks.GRASS_BLOCK.getDefaultState(), 2); 48 | 49 | } 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/postprocessor/OldRiverPostProcessor.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.postprocessor; 2 | 3 | import java.nio.file.Paths; 4 | import java.util.Random; 5 | 6 | import net.minecraft.block.BlockState; 7 | import net.minecraft.block.Blocks; 8 | import net.minecraft.util.math.BlockPos; 9 | import net.minecraft.util.math.MathHelper; 10 | import net.minecraft.world.WorldAccess; 11 | import net.minecraft.world.gen.ChunkRandom; 12 | import supercoder79.simplexterrain.api.Coordinate2Function; 13 | import supercoder79.simplexterrain.api.Heightmap; 14 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 15 | import supercoder79.simplexterrain.api.postprocess.TerrainPostProcessor; 16 | import supercoder79.simplexterrain.configs.ConfigHelper; 17 | import supercoder79.simplexterrain.configs.postprocessors.RiverConfigData; 18 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 19 | 20 | public final class OldRiverPostProcessor implements TerrainPostProcessor { 21 | private RiverConfigData config; 22 | private OpenSimplexNoise noiseSampler; 23 | private OctaveNoiseSampler sandNoise; 24 | private ChunkRandom random; 25 | 26 | @Override 27 | public void init(long seed) { 28 | random = new ChunkRandom(seed); 29 | noiseSampler = new OpenSimplexNoise(seed - 8); 30 | sandNoise = new OctaveNoiseSampler<>(OpenSimplexNoise.class, new Random(seed), config.sandNoiseOctaves,config.sandNoiseFrequency, config.sandNoiseAmplitudeHigh, config.sandNoiseAmplitudeLow); 31 | } 32 | 33 | @Override 34 | public void setup() { 35 | config = ConfigHelper.getFromConfig(RiverConfigData.class, Paths.get("config", "simplexterrain", "postprocessors", "rivers.json")); 36 | } 37 | 38 | @Override 39 | public void process(WorldAccess world, Random rand, int chunkX, int chunkZ, Heightmap heightmap) { 40 | BlockPos.Mutable pos = new BlockPos.Mutable(); 41 | int startX = (chunkX << 4); 42 | int startZ = (chunkZ << 4); 43 | 44 | for (int localX = 0; localX < 16; ++localX) { 45 | int x = localX + startX; 46 | pos.setX(x); 47 | for (int localZ = 0; localZ < 16; ++localZ) { 48 | int z = localZ + startZ; 49 | pos.setZ(z); 50 | double noise = noiseSampler.sample((double) x / config.scale, (double) z / config.scale); 51 | if (noise > 0.12 && noise < 0.15) { 52 | addRiverInChunk(world, heightmap::getHeight, x, z, pos, 0.13 - noise); 53 | } 54 | } 55 | } 56 | } 57 | 58 | private void addRiverInChunk(WorldAccess world, Coordinate2Function heightFunction, final int x, final int z, BlockPos.Mutable pos, double depthNoise) { 59 | int y = heightFunction.apply(x, z) + 1; 60 | int seaLevel = world.getSeaLevel(); 61 | 62 | if (y < seaLevel) { 63 | return; 64 | } 65 | 66 | if (depthNoise < 0) { 67 | depthNoise *= -1; 68 | } 69 | depthNoise = 0.1 - depthNoise; 70 | depthNoise *= (5 * 10); 71 | int depth = (int) depthNoise; 72 | 73 | pos.setY(y); 74 | BlockState bottomBlock = world.getBlockState(pos); 75 | 76 | int waterLevel = calculateWaterLevel(x, z, seaLevel, heightFunction); 77 | int[] neighborWaterLevels = new int[] { 78 | calculateWaterLevel(x+1, z, seaLevel, heightFunction), 79 | calculateWaterLevel(x, z+1, seaLevel, heightFunction), 80 | calculateWaterLevel(x, z-1, seaLevel, heightFunction), 81 | calculateWaterLevel(x-1, z, seaLevel, heightFunction)}; 82 | int higher = 0; 83 | for (int i : neighborWaterLevels) { 84 | if (i < waterLevel) { 85 | higher++; 86 | } 87 | } 88 | 89 | if (higher >= 3) waterLevel = neighborWaterLevels[0]; 90 | 91 | for (int yOffset = 0; yOffset <= depth; ++yOffset) { 92 | --y; 93 | pos.setY(y); 94 | 95 | if (yOffset == 1) { 96 | bottomBlock = world.getBlockState(pos); 97 | } 98 | 99 | world.setBlockState(pos, y >= waterLevel ? AIR : WATER, 2); 100 | 101 | } 102 | 103 | pos.setY(y - 1); 104 | if (sandNoise.sample(x, z) > 0) bottomBlock = Blocks.SAND.getDefaultState(); 105 | world.setBlockState(pos, bottomBlock, 2); 106 | 107 | if (random.nextInt(6) == 0) { 108 | pos.setY(y); 109 | world.setBlockState(pos, random.nextInt(3) > 0 ? Blocks.SEAGRASS.getDefaultState() : Blocks.TALL_SEAGRASS.getDefaultState(), 2); 110 | } 111 | } 112 | 113 | private int calculateWaterLevel(int x, int z, int seaLevel, Coordinate2Function heightFunction) { 114 | int subX = ((x >> 2) << 2); 115 | int subZ = ((z >> 2) << 2); 116 | int subXUpper = subX + 4; 117 | int subZUpper = subZ + 4; 118 | 119 | double xProgress = (double) (x - subX) / 4.0; 120 | double zProgress = (double) (z - subZ) / 4.0; 121 | 122 | double sampleNW = heightFunction.apply(subX, subZ); 123 | double sampleNE = heightFunction.apply(subXUpper, subZ); 124 | double sampleSW = heightFunction.apply(subX, subZUpper); 125 | double sampleSE = heightFunction.apply(subXUpper, subZUpper); 126 | 127 | int returnValue = (int) MathHelper.lerp(zProgress, 128 | MathHelper.lerp(xProgress, sampleNW, sampleNE), 129 | MathHelper.lerp(xProgress, sampleSW, sampleSE)); 130 | 131 | return Math.max(returnValue, seaLevel); 132 | } 133 | 134 | public static final BlockState AIR = Blocks.AIR.getDefaultState(); 135 | public static final BlockState WATER = Blocks.WATER.getDefaultState(); 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/postprocessor/PostProcessors.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.postprocessor; 2 | 3 | import supercoder79.simplexterrain.api.postprocess.TerrainPostProcessor; 4 | 5 | public enum PostProcessors { 6 | // RIVERS(new OldRiverPostProcessor()), 7 | SIMPLEX_CAVES(new SimplexCavesPostProcessor()), 8 | EROSION(new ErosionPostProcessor()), 9 | STRATA(new StrataPostProcessor()), 10 | SOIL(new SoilPostProcessor()); 11 | 12 | public TerrainPostProcessor postProcessor; 13 | 14 | PostProcessors(TerrainPostProcessor postProcessor) { 15 | this.postProcessor = postProcessor; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/postprocessor/SimplexCavesPostProcessor.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.postprocessor; 2 | 3 | import net.minecraft.block.Blocks; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraft.util.math.ChunkPos; 6 | import net.minecraft.world.WorldAccess; 7 | import supercoder79.simplexterrain.api.Heightmap; 8 | import supercoder79.simplexterrain.api.postprocess.PostProcessorTarget; 9 | import supercoder79.simplexterrain.api.postprocess.TerrainPostProcessor; 10 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 11 | import supercoder79.simplexterrain.noise.gradient.SimplexStyleNoise; 12 | 13 | import java.util.Arrays; 14 | import java.util.Random; 15 | 16 | public class SimplexCavesPostProcessor implements TerrainPostProcessor { 17 | private SimplexStyleNoise sampler1; 18 | private SimplexStyleNoise sampler2; 19 | private SimplexStyleNoise threshold; 20 | private SimplexStyleNoise threshold2; 21 | private SimplexStyleNoise[] multiEvalInstances; 22 | 23 | @Override 24 | public void init(long seed) { 25 | sampler1 = new SimplexStyleNoise(seed + 79); 26 | sampler2 = new SimplexStyleNoise(seed - 79); 27 | threshold = new SimplexStyleNoise(seed + 89); 28 | threshold2 = new SimplexStyleNoise(seed - 89); 29 | multiEvalInstances = new SimplexStyleNoise[] { sampler1, sampler2, threshold }; 30 | } 31 | 32 | @Override 33 | public void setup() { 34 | 35 | } 36 | 37 | @Override 38 | public void process(WorldAccess world, Random rand, int chunkX, int chunkZ, Heightmap heightmap) { 39 | int[] heights = heightmap.getHeightsInChunk(new ChunkPos(chunkX, chunkZ)); 40 | 41 | double[] values = new double[multiEvalInstances.length]; 42 | 43 | BlockPos.Mutable pos = new BlockPos.Mutable(); 44 | for (int x = 0; x < 16; x++) { 45 | pos.setX(chunkX*16 + x); 46 | for (int z = 0; z < 16; z++) { 47 | pos.setZ(chunkZ*16 + z); 48 | int h = heights[x*16 + z]+1; 49 | for (int y = 1; y < h; y++) { 50 | 51 | // Begin to compute threshold 52 | double a = (h - y) - 5.0; 53 | if (a < 0) a = 0; else a *= a; 54 | a += 2.3; 55 | double thresholdBase = (0.03125 / (y + 2.0)) - (0.0234375 / a) + 0.0125; 56 | double thresholdAmp1 = 0.06125 / (y + 7.0); 57 | double thresholdSubAmp2 = 0.04625; 58 | 59 | // Reset values for Y, and calculate noises for this block 60 | Arrays.fill(values, 0); 61 | SimplexStyleNoise.noise3_XZBeforeY(multiEvalInstances, pos.getX() / 70f, y / 50f, pos.getZ() / 70f, values); 62 | double d1 = values[0], d2 = values[1], thresholdNoise1 = values[2]; 63 | 64 | // Sum of squared noise values, near zero produces tunnels 65 | double d = (d1 * d1) + (d2 * d2); 66 | 67 | // If the sum of squares is above the maximum value the threshold can take given what we know, 68 | // then we know we don't remove the block here. 69 | double largestPossibleThreshold = thresholdBase + thresholdNoise1 * (thresholdAmp1 + (thresholdNoise1 > 0 ? thresholdSubAmp2 : -thresholdSubAmp2)); 70 | if (d > largestPossibleThreshold) continue; 71 | 72 | // If the sum of squares is below the minimum value the threshold can take given what we know, 73 | // then we know we do remove the block here. 74 | double smallestPossibleThreshold = thresholdBase + thresholdNoise1 * (thresholdAmp1 + (thresholdNoise1 > 0 ? -thresholdSubAmp2 : thresholdSubAmp2)); 75 | boolean removeBlock = (d < smallestPossibleThreshold); 76 | 77 | // If it's in the range where the second threshold noise makes a difference, 78 | // compute that and then we have our final answer. 79 | if (!removeBlock) { 80 | double thresholdNoise2 = threshold2.sample(pos.getX() / 15f, y / 10f, pos.getZ() / 15f); 81 | double threshold = thresholdBase + thresholdNoise1 * (thresholdAmp1 + thresholdNoise2 * thresholdSubAmp2); 82 | removeBlock = (d < threshold); 83 | } 84 | 85 | if (removeBlock) { 86 | pos.setY(y); 87 | if (world.getBlockState(pos) == Blocks.BEDROCK.getDefaultState()) continue; 88 | 89 | if (y < 11) { 90 | world.setBlockState(pos, Blocks.LAVA.getDefaultState(), 0); 91 | } else { 92 | world.setBlockState(pos, Blocks.AIR.getDefaultState(), 0); 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } 99 | 100 | @Override 101 | public PostProcessorTarget getTarget() { 102 | return PostProcessorTarget.CARVERS; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/postprocessor/SoilPostProcessor.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.postprocessor; 2 | 3 | import java.nio.file.Paths; 4 | import java.util.Random; 5 | 6 | import net.minecraft.block.Blocks; 7 | import net.minecraft.util.math.BlockPos; 8 | import net.minecraft.util.math.ChunkPos; 9 | import net.minecraft.world.WorldAccess; 10 | import net.minecraft.world.gen.ChunkRandom; 11 | import supercoder79.simplexterrain.api.Heightmap; 12 | import supercoder79.simplexterrain.api.noise.OctaveNoiseSampler; 13 | import supercoder79.simplexterrain.api.postprocess.TerrainPostProcessor; 14 | import supercoder79.simplexterrain.configs.ConfigHelper; 15 | import supercoder79.simplexterrain.configs.postprocessors.SoilConfigData; 16 | import supercoder79.simplexterrain.noise.gradient.OpenSimplexNoise; 17 | 18 | public class SoilPostProcessor implements TerrainPostProcessor { 19 | private SoilConfigData config; 20 | private OctaveNoiseSampler coarseDirtSampler; 21 | private OctaveNoiseSampler podzolSampler; 22 | 23 | @Override 24 | public void init(long seed) { 25 | coarseDirtSampler = new OctaveNoiseSampler<>(OpenSimplexNoise.class, new ChunkRandom(seed + 42), config.coarseDirtOctaves, config.coarseDirtFrequency, config.coarseDirtAmplitudeHigh, config.coarseDirtAmplitudeLow); 26 | podzolSampler = new OctaveNoiseSampler<>(OpenSimplexNoise.class, new ChunkRandom(seed - 42), config.podzolOctaves, config.podzolFrequency, config.podzolAmplitudeHigh, config.podzolAmplitudeLow); 27 | } 28 | 29 | @Override 30 | public void setup() { 31 | config = ConfigHelper.getFromConfig(SoilConfigData.class, Paths.get("config", "simplexterrain", "postprocessors", "soil.json")); 32 | } 33 | 34 | @Override 35 | public void process(WorldAccess world, Random rand, int chunkX, int chunkZ, Heightmap heightmap) { 36 | int[] height = heightmap.getHeightsInChunk(new ChunkPos(chunkX, chunkZ)); 37 | 38 | BlockPos.Mutable mutable = new BlockPos.Mutable(); 39 | for (int x = 0; x < 16; x++) { 40 | mutable.setX(chunkX*16 + x); 41 | for (int z = 0; z < 16; z++) { 42 | mutable.setZ(chunkZ*16 + z); 43 | mutable.setY(height[x*16 + z]); 44 | 45 | if (world.getBlockState(mutable) == Blocks.GRASS_BLOCK.getDefaultState()) { 46 | if (coarseDirtSampler.sample(mutable.getX(), mutable.getZ()) > config.coarseDirtThreshold) 47 | world.setBlockState(mutable, Blocks.COARSE_DIRT.getDefaultState(), 0); 48 | if (podzolSampler.sample(mutable.getX(), mutable.getZ()) < config.podzolThreshold) 49 | world.setBlockState(mutable, Blocks.PODZOL.getDefaultState(), 0); 50 | } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/supercoder79/simplexterrain/world/postprocessor/StrataPostProcessor.java: -------------------------------------------------------------------------------- 1 | package supercoder79.simplexterrain.world.postprocessor; 2 | 3 | import java.util.Random; 4 | 5 | import net.minecraft.block.BlockState; 6 | import net.minecraft.block.Blocks; 7 | import net.minecraft.util.math.BlockPos; 8 | import net.minecraft.util.math.ChunkPos; 9 | import net.minecraft.world.WorldAccess; 10 | import supercoder79.simplexterrain.api.Heightmap; 11 | import supercoder79.simplexterrain.api.postprocess.TerrainPostProcessor; 12 | 13 | public class StrataPostProcessor implements TerrainPostProcessor { 14 | private static final BlockState[] states = new BlockState[32]; 15 | 16 | @Override 17 | public void init(long seed) { 18 | } 19 | 20 | @Override 21 | public void setup() { 22 | for (int i = 0; i < 4; i++) { 23 | states[i*8] = Blocks.STONE.getDefaultState(); 24 | states[i*8 + 1] = Blocks.ANDESITE.getDefaultState(); 25 | states[i*8 + 2] = Blocks.GRANITE.getDefaultState(); 26 | states[i*8 + 3] = Blocks.GRANITE.getDefaultState(); 27 | states[i*8 + 4] = Blocks.STONE.getDefaultState(); 28 | states[i*8 + 5] = Blocks.DIORITE.getDefaultState(); 29 | states[i*8 + 6] = Blocks.ANDESITE.getDefaultState(); 30 | states[i*8 + 7] = Blocks.STONE.getDefaultState(); 31 | } 32 | } 33 | 34 | @Override 35 | public void process(WorldAccess world, Random rand, int chunkX, int chunkZ, Heightmap heightmap) { 36 | int[] heights = heightmap.getHeightsInChunk(new ChunkPos(chunkX, chunkZ)); 37 | BlockPos.Mutable mutable = new BlockPos.Mutable(); 38 | for (int x = 0; x < 16; x++) { 39 | mutable.setX(chunkX*16 + x); 40 | for (int z = 0; z < 16; z++) { 41 | mutable.setZ(chunkZ*16 + z); 42 | for (int y = heights[x* 16 + z]; y > 0; y--) { 43 | mutable.setY(y); 44 | if (world.getBlockState(mutable) == Blocks.STONE.getDefaultState()) world.setBlockState(mutable, states[y/8], 2); 45 | } 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/resources/assets/simplexterrain/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaskarth/simplexterrain/39d74e99bf060741b40bede9ba3a57ae7fced6b4/src/main/resources/assets/simplexterrain/icon.png -------------------------------------------------------------------------------- /src/main/resources/assets/simplexterrain/lang/en_us.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator.simplex": "Simplex Terrain" 3 | } -------------------------------------------------------------------------------- /src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "simplexterrain", 4 | "version": "0.7.2", 5 | 6 | "name": "Simplex Terrain", 7 | "description": "Creates worlds with terrain unlike anything else!", 8 | "authors": [ 9 | "SuperCoder79", 10 | "Valoeghese" 11 | ], 12 | "contact": { 13 | "homepage": "", 14 | "sources": "" 15 | }, 16 | 17 | "license": "LGPLv3", 18 | "icon": "assets/simplexterrain/icon.png", 19 | 20 | "accessWidener" : "simplexterrain.aw", 21 | 22 | "environment": "*", 23 | "entrypoints": { 24 | "main": [ 25 | "supercoder79.simplexterrain.SimplexTerrain" 26 | ] 27 | }, 28 | "mixins": [ 29 | "simplexterrain.mixins.json" 30 | ], 31 | 32 | "depends": { 33 | "fabricloader": ">=0.7.0", 34 | "fabric": "*" 35 | }, 36 | 37 | "suggests": { 38 | "winterbiomemod": "*", 39 | "traverse": "*", 40 | "terrestria": "*" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/resources/simplexterrain.aw: -------------------------------------------------------------------------------- 1 | accessWidener v1 named 2 | 3 | accessible method net/minecraft/client/world/GeneratorType (Ljava/lang/String;)V 4 | accessible field net/minecraft/world/biome/source/VanillaLayeredBiomeSource BIOMES Ljava/util/List; -------------------------------------------------------------------------------- /src/main/resources/simplexterrain.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "supercoder79.simplexterrain.mixin", 4 | "compatibilityLevel": "JAVA_8", 5 | "mixins": [ 6 | "MixinNoiseChunkGenerator", 7 | "MixinChunkStatus", 8 | "MixinGeneratorOptions", 9 | "MixinMinecraftServer", 10 | "MixinSpawnLocating", 11 | "antibad.MixinLakeFeature", 12 | "optichunk.MixinChunkSection" 13 | ], 14 | "client": [ 15 | "client.MixinSkyProperties", 16 | "client.MixinMinecraftClient" 17 | ], 18 | "injectors": { 19 | "defaultRequire": 1 20 | } 21 | } 22 | --------------------------------------------------------------------------------