├── .gitignore ├── README.md ├── build.gradle.kts ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle.kts └── src ├── common ├── blockswap.mixins.json └── main │ └── java │ └── dev │ └── corgitaco │ └── blockswap │ ├── BlockSwap.java │ ├── data │ ├── BlockSwapLevelChunkData.java │ └── BlockSwapProtoChunkData.java │ ├── itempredicate │ ├── ItemIsPredicate.java │ └── ItemPredicate.java │ ├── mixin │ └── LevelChunkSectionMixin.java │ ├── swappredicate │ ├── AllOfBlockSwapPredicate.java │ ├── AnyOfBlockSwapPredicate.java │ ├── BiomeHumidityExceedsBlockSwapPredicate.java │ ├── BiomeIsBlockSwapPredicate.java │ ├── BiomeTempExceedsBlockSwapPredicate.java │ ├── BlockSwapPredicate.java │ ├── ChunkTimeExceedsBlockSwapPredicate.java │ ├── ConditionsPassBlockSwapPredicate.java │ ├── ContainerHasAllItemsBlockSwapPredicate.java │ ├── ContainerHasAnyItemsBlockSwapPredicate.java │ ├── DimensionBlockSwapPredicate.java │ ├── InverseBlockSwapPredicate.java │ ├── IsBlockEntityBlockSwapPredicate.java │ ├── IsWorldGenerationBlockSwapPredicate.java │ └── SkipChunkHasMarkerBlockSwapPredicate.java │ └── util │ └── ChunkSectionBlockStateSwapper.java ├── fabric └── main │ └── java │ └── dev │ └── corgitaco │ └── blockswap │ └── fabric │ └── FabricBlockSwap.java ├── forge └── main │ └── java │ └── dev │ └── corgitaco │ └── blockswap │ └── ForgeBlockSwap.java └── neoforge └── main └── java └── dev └── corgitaco └── blockswap └── neoforge └── NeoforgeBlockSwap.java /.gitignore: -------------------------------------------------------------------------------- 1 | run 2 | 3 | .gradle 4 | build/ 5 | !gradle/wrapper/gradle-wrapper.jar 6 | !**/src/main/**/build/ 7 | !**/src/test/**/build/ 8 | 9 | ### IntelliJ IDEA ### 10 | .idea/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | out/ 15 | !**/src/main/**/out/ 16 | !**/src/test/**/out/ 17 | 18 | ### Eclipse ### 19 | .apt_generated 20 | .classpath 21 | .factorypath 22 | .project 23 | .settings 24 | .springBeans 25 | .sts4-cache 26 | bin/ 27 | !**/src/main/**/bin/ 28 | !**/src/test/**/bin/ 29 | 30 | ### NetBeans ### 31 | /nbproject/private/ 32 | /nbbuild/ 33 | /dist/ 34 | /nbdist/ 35 | /.nb-gradle/ 36 | 37 | ### VS Code ### 38 | .vscode/ 39 | 40 | ### Mac OS ### 41 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Block Swap -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("earth.terrarium.cloche") version "0.8.20" 3 | } 4 | 5 | group = "dev.corgitaco" 6 | version = "1.0.0" 7 | 8 | repositories { 9 | mavenCentral() 10 | maven("https://maven.jt-dev.tech/releases") 11 | maven("https://maven.jt-dev.tech/snapshots") 12 | 13 | cloche { 14 | librariesMinecraft() 15 | main() 16 | 17 | mavenFabric() 18 | mavenNeoforged() 19 | } 20 | } 21 | 22 | cloche { 23 | minecraftVersion = "1.21.1" 24 | 25 | 26 | metadata { 27 | modId = "blockswap" 28 | name = "Block Swap" 29 | license = "ARR" 30 | description = "Hello!" 31 | dependency { 32 | modId = "dataanchor" 33 | required = true 34 | version("2.0.0.3") 35 | } 36 | } 37 | 38 | common { 39 | dependencies { 40 | compileOnly("io.github.llamalad7:mixinextras-fabric:${project.properties["mixinextras_version"]}") 41 | } 42 | } 43 | 44 | forge { 45 | loaderVersion = "52.1.0" 46 | 47 | runs { 48 | server() 49 | client() 50 | } 51 | val mixinExtras = module("io.github.llamalad7:mixinextras-forge:${project.properties["mixinextras_version"]}") 52 | 53 | 54 | include(mixinExtras) 55 | project.dependencies.add("forgeAnnotationProcessor", mixinExtras) 56 | 57 | dependencies { 58 | modApi(mixinExtras) 59 | modApi("dev.corgitaco:Data_Anchor-forge-${minecraftVersion.get()}:${project.properties["data_anchor_version"]}") 60 | } 61 | } 62 | 63 | neoforge { 64 | loaderVersion = "21.1.135" 65 | mixins.from(file("src/common/blockswap.mixins.json")) 66 | 67 | data() 68 | 69 | runs { 70 | server() 71 | client() 72 | data() 73 | } 74 | 75 | dependencies { 76 | modApi("dev.corgitaco:Data_Anchor-neoforge-${minecraftVersion.get()}:${project.properties["data_anchor_version"]}") 77 | } 78 | } 79 | 80 | fabric { 81 | loaderVersion = "0.16.10" 82 | mixins.from(file("src/common/blockswap.mixins.json")) 83 | 84 | metadata { 85 | entrypoint("main", "dev.corgitaco.blockswap.fabric.FabricBlockSwap::initialize") 86 | dependency { 87 | modId = "fabric-api" 88 | required = true 89 | } 90 | } 91 | 92 | data() 93 | client() 94 | 95 | dependencies { 96 | fabricApi("0.115.2+1.21.1") 97 | modApi("dev.corgitaco:Data_Anchor-fabric-${minecraftVersion.get()}:${project.properties["data_anchor_version"]}") 98 | } 99 | 100 | runs { 101 | server() 102 | client() 103 | data() 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G 2 | 3 | org.gradle.configureondemand=true 4 | org.gradle.parallel=true 5 | org.gradle.caching=true 6 | 7 | # Dependencies 8 | data_anchor_version=2.0.0.4 9 | mixinextras_version=0.4.1 10 | 11 | # TODO Enable when fully working 12 | # org.gradle.configuration-cache=true 13 | # org.gradle.unsafe.isolated-projects=true 14 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CorgiTaco-MC/Block-Swap/17a68df4f2e9762bf799265fcae2e15691827882/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original 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 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | if ! command -v java >/dev/null 2>&1 137 | then 138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 139 | 140 | Please set the JAVA_HOME variable in your environment to match the 141 | location of your Java installation." 142 | fi 143 | fi 144 | 145 | # Increase the maximum file descriptors if we can. 146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 147 | case $MAX_FD in #( 148 | max*) 149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 150 | # shellcheck disable=SC2039,SC3045 151 | MAX_FD=$( ulimit -H -n ) || 152 | warn "Could not query maximum file descriptor limit" 153 | esac 154 | case $MAX_FD in #( 155 | '' | soft) :;; #( 156 | *) 157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 158 | # shellcheck disable=SC2039,SC3045 159 | ulimit -n "$MAX_FD" || 160 | warn "Could not set maximum file descriptor limit to $MAX_FD" 161 | esac 162 | fi 163 | 164 | # Collect all arguments for the java command, stacking in reverse order: 165 | # * args from the command line 166 | # * the main class name 167 | # * -classpath 168 | # * -D...appname settings 169 | # * --module-path (only if needed) 170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 171 | 172 | # For Cygwin or MSYS, switch paths to Windows format before running java 173 | if "$cygwin" || "$msys" ; then 174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 176 | 177 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 178 | 179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 180 | for arg do 181 | if 182 | case $arg in #( 183 | -*) false ;; # don't mess with options #( 184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 185 | [ -e "$t" ] ;; #( 186 | *) false ;; 187 | esac 188 | then 189 | arg=$( cygpath --path --ignore --mixed "$arg" ) 190 | fi 191 | # Roll the args list around exactly as many times as the number of 192 | # args, so each arg winds up back in the position where it started, but 193 | # possibly modified. 194 | # 195 | # NB: a `for` loop captures its iteration list before it begins, so 196 | # changing the positional parameters here affects neither the number of 197 | # iterations, nor the values presented in `arg`. 198 | shift # remove old arg 199 | set -- "$@" "$arg" # push replacement arg 200 | done 201 | fi 202 | 203 | 204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 206 | 207 | # Collect all arguments for the java command: 208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 209 | # and any embedded shellness will be escaped. 210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 211 | # treated as '${Hostname}' itself on the command line. 212 | 213 | set -- \ 214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 215 | -classpath "$CLASSPATH" \ 216 | org.gradle.wrapper.GradleWrapperMain \ 217 | "$@" 218 | 219 | # Stop when "xargs" is not available. 220 | if ! command -v xargs >/dev/null 2>&1 221 | then 222 | die "xargs is not available" 223 | fi 224 | 225 | # Use "xargs" to parse quoted args. 226 | # 227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 228 | # 229 | # In Bash we could simply go: 230 | # 231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 232 | # set -- "${ARGS[@]}" "$@" 233 | # 234 | # but POSIX shell has neither arrays nor command substitution, so instead we 235 | # post-process each arg (as a line of input to sed) to backslash-escape any 236 | # character that might be a shell metacharacter, then use eval to reverse 237 | # that process (while maintaining the separation between arguments), and wrap 238 | # the whole thing up as a single "set" statement. 239 | # 240 | # This will of course break if any of these variables contains a newline or 241 | # an unmatched quote. 242 | # 243 | 244 | eval "set -- $( 245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 246 | xargs -n1 | 247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 248 | tr '\n' ' ' 249 | )" '"$@"' 250 | 251 | exec "$JAVACMD" "$@" 252 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "Block Swap" 2 | 3 | pluginManagement { 4 | repositories { 5 | maven(url = "https://maven.msrandom.net/repository/cloche") 6 | 7 | gradlePluginPortal() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/common/blockswap.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "dev.corgitaco.blockswap.mixin", 4 | "compatibilityLevel": "JAVA_21", 5 | "minVersion": "0.8", 6 | "client": [ 7 | ], 8 | "mixins": [ 9 | "LevelChunkSectionMixin" 10 | ], 11 | "injectors": { 12 | "defaultRequire": 1 13 | }, 14 | "mixinextras": { 15 | "minVersion": "0.4.1" 16 | } 17 | } -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/BlockSwap.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap; 2 | 3 | import dev.corgitaco.blockswap.data.BlockSwapLevelChunkData; 4 | import dev.corgitaco.blockswap.data.BlockSwapProtoChunkData; 5 | import dev.corgitaco.dataanchor.data.registry.TrackedDataKey; 6 | import dev.corgitaco.dataanchor.data.registry.TrackedDataRegistries; 7 | import net.minecraft.resources.ResourceLocation; 8 | import net.minecraft.world.level.chunk.ImposterProtoChunk; 9 | import net.minecraft.world.level.chunk.LevelChunk; 10 | import net.minecraft.world.level.chunk.ProtoChunk; 11 | 12 | public class BlockSwap { 13 | public static final String MOD_ID = "blockswap"; 14 | 15 | public static final TrackedDataKey BLOCK_SWAP_CHUNK_DATA = TrackedDataRegistries.CHUNK.register( 16 | id("block_swap_level_data"), 17 | BlockSwapLevelChunkData.class, 18 | (trackedDataKey, chunkAccess) -> { 19 | if (chunkAccess instanceof LevelChunk chunk) { 20 | return new BlockSwapLevelChunkData(trackedDataKey, chunk); 21 | } 22 | return null; 23 | } 24 | ); 25 | 26 | public static final TrackedDataKey BLOCK_SWAP_WORLD_GEN_DATA = TrackedDataRegistries.CHUNK.register( 27 | id("block_swap_world_gen_data"), 28 | BlockSwapProtoChunkData.class, 29 | (trackedDataKey, chunkAccess) -> { 30 | if (chunkAccess instanceof ProtoChunk chunk && !(chunkAccess instanceof ImposterProtoChunk)) { 31 | return new BlockSwapProtoChunkData(trackedDataKey, chunk); 32 | } 33 | return null; 34 | } 35 | ); 36 | 37 | public static void initialize() { 38 | System.out.println("Hello World!"); 39 | } 40 | 41 | public static ResourceLocation id(String path) { 42 | return ResourceLocation.fromNamespaceAndPath(MOD_ID, path); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/data/BlockSwapLevelChunkData.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.data; 2 | 3 | import dev.corgitaco.dataanchor.data.registry.TrackedDataKey; 4 | import dev.corgitaco.dataanchor.data.type.chunk.ChunkBlockStateInterceptor; 5 | import dev.corgitaco.dataanchor.data.type.chunk.LevelChunkTrackedData; 6 | import dev.corgitaco.dataanchor.data.type.chunk.ServerLevelChunkTrackedData; 7 | import dev.corgitaco.dataanchor.data.type.chunk.SyncedLevelChunkTrackedData; 8 | import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; 9 | import net.minecraft.Util; 10 | import net.minecraft.core.BlockPos; 11 | import net.minecraft.nbt.CompoundTag; 12 | import net.minecraft.world.level.block.Blocks; 13 | import net.minecraft.world.level.block.state.BlockState; 14 | import net.minecraft.world.level.chunk.LevelChunk; 15 | 16 | import java.util.HashSet; 17 | import java.util.Map; 18 | import java.util.Set; 19 | 20 | public class BlockSwapLevelChunkData extends ServerLevelChunkTrackedData implements ChunkBlockStateInterceptor { 21 | 22 | private final Set placeHolders = new HashSet<>(); 23 | 24 | Map blockStateMap = Util.make(new Reference2ReferenceOpenHashMap<>(), map -> map.put(Blocks.STONE.defaultBlockState(), Blocks.WATER.defaultBlockState())); 25 | 26 | 27 | public BlockSwapLevelChunkData(TrackedDataKey trackedDataKey, LevelChunk levelChunk) { 28 | super(trackedDataKey, levelChunk); 29 | } 30 | 31 | 32 | @Override 33 | public CompoundTag save() { 34 | return super.save(); 35 | } 36 | 37 | @Override 38 | public void load(CompoundTag compoundTag) { 39 | } 40 | 41 | @Override 42 | public BlockState getNewState(BlockPos blockPos, BlockState blockState, BlockState blockState1, boolean b) { 43 | return blockStateMap.getOrDefault(blockState, blockState1); 44 | } 45 | 46 | public Set getPlaceHolders() { 47 | return placeHolders; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/data/BlockSwapProtoChunkData.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.data; 2 | 3 | import dev.corgitaco.blockswap.util.ChunkSectionBlockStateSwapper; 4 | import dev.corgitaco.dataanchor.data.registry.TrackedDataKey; 5 | import dev.corgitaco.dataanchor.data.type.chunk.ChunkTrackedData; 6 | import dev.corgitaco.dataanchor.data.type.chunk.ProtoChunkTrackedData; 7 | import it.unimi.dsi.fastutil.ints.Int2IntMaps; 8 | import net.minecraft.world.level.block.Block; 9 | import net.minecraft.world.level.block.Blocks; 10 | import net.minecraft.world.level.chunk.LevelChunkSection; 11 | import net.minecraft.world.level.chunk.ProtoChunk; 12 | 13 | import java.util.HashSet; 14 | import java.util.Set; 15 | 16 | public class BlockSwapProtoChunkData extends ProtoChunkTrackedData { 17 | 18 | private final Set placeHolders = new HashSet<>(); 19 | 20 | public BlockSwapProtoChunkData(TrackedDataKey trackedDataKey, ProtoChunk protoChunk) { 21 | super(trackedDataKey, protoChunk); 22 | 23 | for (LevelChunkSection section : protoChunk.getSections()) { 24 | if (section instanceof ChunkSectionBlockStateSwapper chunkSectionBlockStateSwapper) { 25 | chunkSectionBlockStateSwapper.blockSwap$createSwapper(Int2IntMaps.singleton(Block.BLOCK_STATE_REGISTRY.getId(Blocks.STONE.defaultBlockState()), Block.BLOCK_STATE_REGISTRY.getId(Blocks.WATER.defaultBlockState()))); 26 | } 27 | } 28 | } 29 | 30 | public Set getPlaceHolders() { 31 | return placeHolders; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/itempredicate/ItemIsPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.itempredicate; 2 | 3 | import com.mojang.datafixers.util.Either; 4 | import net.minecraft.resources.ResourceKey; 5 | import net.minecraft.tags.TagKey; 6 | import net.minecraft.world.item.Item; 7 | import net.minecraft.world.item.ItemStack; 8 | 9 | import java.util.Optional; 10 | 11 | public record ItemIsPredicate(Either, TagKey> check) implements ItemPredicate { 12 | @Override 13 | public boolean test(ItemStack stack) { 14 | Optional> left = check.left(); 15 | if (left.isPresent()) { 16 | return stack.is(itemHolder -> itemHolder.unwrapKey().orElseThrow() == left.get()); 17 | } 18 | 19 | Optional> right = check.right(); 20 | if (right.isPresent()) { 21 | return stack.is(right.orElseThrow()); 22 | } 23 | 24 | return false; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/itempredicate/ItemPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.itempredicate; 2 | 3 | import net.minecraft.world.item.ItemStack; 4 | 5 | public interface ItemPredicate { 6 | 7 | 8 | 9 | boolean test(ItemStack stack); 10 | } 11 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/mixin/LevelChunkSectionMixin.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.mixin; 2 | 3 | import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; 4 | import com.llamalad7.mixinextras.injector.wrapoperation.Operation; 5 | import dev.corgitaco.blockswap.util.ChunkSectionBlockStateSwapper; 6 | import it.unimi.dsi.fastutil.ints.Int2IntMap; 7 | import net.minecraft.world.level.block.Block; 8 | import net.minecraft.world.level.block.state.BlockState; 9 | import net.minecraft.world.level.chunk.LevelChunkSection; 10 | import org.jetbrains.annotations.Nullable; 11 | import org.spongepowered.asm.mixin.Mixin; 12 | import org.spongepowered.asm.mixin.Unique; 13 | 14 | @Mixin(LevelChunkSection.class) 15 | public class LevelChunkSectionMixin implements ChunkSectionBlockStateSwapper { 16 | 17 | @Unique 18 | @Nullable 19 | private Int2IntMap swapper; 20 | 21 | @WrapMethod(method = "setBlockState(IIILnet/minecraft/world/level/block/state/BlockState;Z)Lnet/minecraft/world/level/block/state/BlockState;") 22 | private BlockState blockSwap$SwapBlockState(int x, int y, int z, BlockState blockState, boolean b, Operation original) { 23 | if (swapper == null) { 24 | return original.call(x, y, z, blockState, b); 25 | } 26 | 27 | int id = swapper.getOrDefault(Block.BLOCK_STATE_REGISTRY.getId(blockState), -1); 28 | if (id == -1) { 29 | return original.call(x, y, z, blockState, b); 30 | } else { 31 | BlockState newState = Block.BLOCK_STATE_REGISTRY.byId(id); 32 | return original.call(x, y, z, newState, b); 33 | } 34 | } 35 | 36 | @Override 37 | public void blockSwap$createSwapper(Int2IntMap swapper) { 38 | this.swapper = swapper; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/AllOfBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import net.minecraft.world.level.Level; 4 | import net.minecraft.world.level.block.state.BlockState; 5 | import net.minecraft.world.level.chunk.ChunkAccess; 6 | 7 | import java.util.List; 8 | 9 | public record AllOfBlockSwapPredicate(List predicates) implements BlockSwapPredicate { 10 | 11 | 12 | @Override 13 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 14 | for (BlockSwapPredicate predicate : this.predicates) { 15 | if (!predicate.test(level, chunk, localX, localY, localZ, lastState)) { 16 | return false; 17 | } 18 | } 19 | 20 | return true; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/AnyOfBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import net.minecraft.world.level.Level; 4 | import net.minecraft.world.level.block.state.BlockState; 5 | import net.minecraft.world.level.chunk.ChunkAccess; 6 | 7 | import java.util.List; 8 | 9 | public record AnyOfBlockSwapPredicate(List predicates) implements BlockSwapPredicate { 10 | 11 | @Override 12 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 13 | for (BlockSwapPredicate predicate : this.predicates) { 14 | if (!predicate.test(level, chunk, localX, localY, localZ, lastState)) { 15 | return true; 16 | } 17 | } 18 | 19 | return false; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/BiomeHumidityExceedsBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.world.level.Level; 5 | import net.minecraft.world.level.block.state.BlockState; 6 | import net.minecraft.world.level.chunk.ChunkAccess; 7 | 8 | import java.util.function.Supplier; 9 | 10 | public record BiomeHumidityExceedsBlockSwapPredicate(float humidity, boolean useFiddle) implements BlockSwapPredicate { 11 | 12 | private static final ThreadLocal POS = ThreadLocal.withInitial(BlockPos.MutableBlockPos::new); 13 | 14 | private static final Supplier POS_SUPPLIER = POS::get; 15 | 16 | @Override 17 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 18 | return getBiome(level, chunk, localX, localY, localZ, POS_SUPPLIER, this.useFiddle).value().climateSettings.getDownFall() > humidity; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/BiomeIsBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import com.mojang.datafixers.util.Either; 4 | import net.minecraft.core.BlockPos; 5 | import net.minecraft.core.Holder; 6 | import net.minecraft.resources.ResourceKey; 7 | import net.minecraft.tags.TagKey; 8 | import net.minecraft.world.level.Level; 9 | import net.minecraft.world.level.biome.Biome; 10 | import net.minecraft.world.level.block.state.BlockState; 11 | import net.minecraft.world.level.chunk.ChunkAccess; 12 | 13 | import java.util.function.Supplier; 14 | 15 | public record BiomeIsBlockSwapPredicate(Either, TagKey> check, boolean useFiddle) implements BlockSwapPredicate { 16 | private static final ThreadLocal POS = ThreadLocal.withInitial(BlockPos.MutableBlockPos::new); 17 | private static final Supplier POS_SUPPLIER = POS::get; 18 | 19 | 20 | @Override 21 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 22 | Holder biome = getBiome(level, chunk, localX, localY, localZ, POS_SUPPLIER, this.useFiddle); 23 | 24 | if (check.left().isPresent()) { 25 | biome.is(check.left().get()); 26 | } 27 | if (check.right().isPresent()) { 28 | return biome.is(check.right().get()); 29 | } 30 | 31 | return false; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/BiomeTempExceedsBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.world.level.Level; 5 | import net.minecraft.world.level.block.state.BlockState; 6 | import net.minecraft.world.level.chunk.ChunkAccess; 7 | 8 | import java.util.function.Supplier; 9 | 10 | public record BiomeTempExceedsBlockSwapPredicate(float temp, boolean useBaseTemperature, boolean useFiddle) implements BlockSwapPredicate { 11 | 12 | private static final ThreadLocal POS = ThreadLocal.withInitial(BlockPos.MutableBlockPos::new); 13 | 14 | private static final Supplier POS_SUPPLIER = POS::get; 15 | 16 | @Override 17 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 18 | 19 | if (useBaseTemperature) { 20 | return getBiome(level, chunk, localX, localY, localZ, POS::get, this.useFiddle).value().getBaseTemperature() > temp; 21 | } else { 22 | BlockPos.MutableBlockPos mutableBlockPos = POS.get(); 23 | return getBiome(level, chunk, localX, localY, localZ, POS_SUPPLIER, this.useFiddle).value().getTemperature(mutableBlockPos) > temp; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/BlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import net.minecraft.core.BlockPos; 4 | import net.minecraft.core.Holder; 5 | import net.minecraft.world.level.ChunkPos; 6 | import net.minecraft.world.level.Level; 7 | import net.minecraft.world.level.biome.Biome; 8 | import net.minecraft.world.level.block.state.BlockState; 9 | import net.minecraft.world.level.chunk.ChunkAccess; 10 | 11 | import java.util.function.Supplier; 12 | 13 | public interface BlockSwapPredicate { 14 | 15 | 16 | boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState); 17 | 18 | default Holder getBiome(Level level, ChunkAccess chunk, int localX, int localY, int localZ, Supplier mutableBlockPosSupplier, boolean useFiddle) { 19 | if (!useFiddle) { 20 | return chunk.getNoiseBiome(localX, localY, localZ); 21 | } else { 22 | ChunkPos pos = chunk.getPos(); 23 | BlockPos.MutableBlockPos mutableBlockPos = mutableBlockPosSupplier.get(); 24 | mutableBlockPos.set(pos.getBlockX(localX), localY, pos.getBlockZ(localZ)); 25 | return level.getBiome(mutableBlockPos); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/ChunkTimeExceedsBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import net.minecraft.world.level.Level; 4 | import net.minecraft.world.level.block.state.BlockState; 5 | import net.minecraft.world.level.chunk.ChunkAccess; 6 | 7 | public record ChunkTimeExceedsBlockSwapPredicate(long threshold) implements BlockSwapPredicate { 8 | 9 | 10 | @Override 11 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 12 | return chunk.getInhabitedTime() < threshold; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/ConditionsPassBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import net.minecraft.world.level.Level; 4 | import net.minecraft.world.level.block.state.BlockState; 5 | import net.minecraft.world.level.chunk.ChunkAccess; 6 | 7 | import java.util.List; 8 | 9 | public record ConditionsPassBlockSwapPredicate(List predicates, int passedConditions) implements BlockSwapPredicate { 10 | 11 | @Override 12 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 13 | int passedConditions = 0; 14 | 15 | for (BlockSwapPredicate predicate : this.predicates) { 16 | if (predicate.test(level, chunk, localX, localY, localZ, lastState)) { 17 | passedConditions++; 18 | if (passedConditions >= this.passedConditions) { 19 | return true; 20 | } 21 | } 22 | } 23 | 24 | return false; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/ContainerHasAllItemsBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import dev.corgitaco.blockswap.itempredicate.ItemPredicate; 4 | import net.minecraft.core.BlockPos; 5 | import net.minecraft.world.Container; 6 | import net.minecraft.world.level.Level; 7 | import net.minecraft.world.level.block.entity.BlockEntity; 8 | import net.minecraft.world.level.block.state.BlockState; 9 | import net.minecraft.world.level.chunk.ChunkAccess; 10 | 11 | import java.util.List; 12 | import java.util.function.Supplier; 13 | 14 | public record ContainerHasAllItemsBlockSwapPredicate(List itemChecks) implements BlockSwapPredicate { 15 | private static final ThreadLocal POS = ThreadLocal.withInitial(BlockPos.MutableBlockPos::new); 16 | 17 | private static final Supplier POS_SUPPLIER = POS::get; 18 | 19 | 20 | @Override 21 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 22 | BlockPos.MutableBlockPos mutableBlockPos = POS.get(); 23 | mutableBlockPos.set(localX, localY, localZ); 24 | BlockEntity blockEntity = chunk.getBlockEntity(mutableBlockPos); 25 | if (blockEntity instanceof Container container) { 26 | for (ItemPredicate itemCheck : this.itemChecks) { 27 | if (!container.hasAnyMatching(itemCheck::test)) { 28 | return false; 29 | } 30 | } 31 | } 32 | 33 | 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/ContainerHasAnyItemsBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import dev.corgitaco.blockswap.itempredicate.ItemPredicate; 4 | import net.minecraft.core.BlockPos; 5 | import net.minecraft.world.Container; 6 | import net.minecraft.world.level.Level; 7 | import net.minecraft.world.level.block.entity.BlockEntity; 8 | import net.minecraft.world.level.block.state.BlockState; 9 | import net.minecraft.world.level.chunk.ChunkAccess; 10 | 11 | import java.util.List; 12 | import java.util.function.Supplier; 13 | 14 | public record ContainerHasAnyItemsBlockSwapPredicate(List itemChecks) implements BlockSwapPredicate { 15 | private static final ThreadLocal POS = ThreadLocal.withInitial(BlockPos.MutableBlockPos::new); 16 | 17 | private static final Supplier POS_SUPPLIER = POS::get; 18 | 19 | 20 | @Override 21 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 22 | BlockPos.MutableBlockPos mutableBlockPos = POS.get(); 23 | mutableBlockPos.set(localX, localY, localZ); 24 | BlockEntity blockEntity = chunk.getBlockEntity(mutableBlockPos); 25 | if (blockEntity instanceof Container container) { 26 | for (ItemPredicate itemCheck : this.itemChecks) { 27 | if (container.hasAnyMatching(itemCheck::test)) { 28 | return true; 29 | } 30 | } 31 | } 32 | return false; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/DimensionBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import net.minecraft.resources.ResourceKey; 4 | import net.minecraft.world.level.Level; 5 | import net.minecraft.world.level.block.state.BlockState; 6 | import net.minecraft.world.level.chunk.ChunkAccess; 7 | 8 | public record DimensionBlockSwapPredicate(ResourceKey levelResourceKey) implements BlockSwapPredicate { 9 | 10 | @Override 11 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 12 | return level.dimension() == levelResourceKey; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/InverseBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import net.minecraft.world.level.Level; 4 | import net.minecraft.world.level.block.state.BlockState; 5 | import net.minecraft.world.level.chunk.ChunkAccess; 6 | 7 | public record InverseBlockSwapPredicate(BlockSwapPredicate predicate) implements BlockSwapPredicate { 8 | 9 | 10 | @Override 11 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 12 | return !this.predicate.test(level, chunk, localX, localY, localZ, lastState); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/IsBlockEntityBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import com.mojang.datafixers.util.Either; 4 | import net.minecraft.core.BlockPos; 5 | import net.minecraft.resources.ResourceKey; 6 | import net.minecraft.tags.TagKey; 7 | import net.minecraft.world.level.Level; 8 | import net.minecraft.world.level.block.entity.BlockEntity; 9 | import net.minecraft.world.level.block.entity.BlockEntityType; 10 | import net.minecraft.world.level.block.state.BlockState; 11 | import net.minecraft.world.level.chunk.ChunkAccess; 12 | 13 | import java.util.Optional; 14 | 15 | public record IsBlockEntityBlockSwapPredicate(Optional>, TagKey>>> check, 16 | boolean useFiddle) implements BlockSwapPredicate { 17 | 18 | private static final ThreadLocal POS = ThreadLocal.withInitial(BlockPos.MutableBlockPos::new); 19 | 20 | @Override 21 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 22 | BlockPos.MutableBlockPos mutableBlockPos = POS.get(); 23 | mutableBlockPos.set(localX, localY, localZ); 24 | BlockEntity blockEntity = chunk.getBlockEntity(mutableBlockPos); 25 | if (blockEntity == null) { 26 | return false; 27 | } 28 | 29 | if (check().isPresent()) { 30 | Either>, TagKey>> resourceKeyTagKeyEither = check.orElseThrow(); 31 | 32 | Optional>> left = resourceKeyTagKeyEither.left(); 33 | if (left.isPresent()) { 34 | return blockEntity.getType().builtInRegistryHolder().is(left.get()); 35 | } 36 | Optional>> right = resourceKeyTagKeyEither.right(); 37 | if (right.isPresent()) { 38 | return blockEntity.getType().builtInRegistryHolder().is(right.get()); 39 | } 40 | } 41 | 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/IsWorldGenerationBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import net.minecraft.world.level.Level; 4 | import net.minecraft.world.level.block.state.BlockState; 5 | import net.minecraft.world.level.chunk.ChunkAccess; 6 | import net.minecraft.world.level.chunk.ImposterProtoChunk; 7 | import net.minecraft.world.level.chunk.ProtoChunk; 8 | 9 | public class IsWorldGenerationBlockSwapPredicate implements BlockSwapPredicate { 10 | @Override 11 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 12 | return chunk instanceof ProtoChunk && !(chunk instanceof ImposterProtoChunk); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/swappredicate/SkipChunkHasMarkerBlockSwapPredicate.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.swappredicate; 2 | 3 | import dev.corgitaco.blockswap.BlockSwap; 4 | import dev.corgitaco.blockswap.data.BlockSwapLevelChunkData; 5 | import dev.corgitaco.blockswap.data.BlockSwapProtoChunkData; 6 | import dev.corgitaco.dataanchor.data.registry.TrackedDataRegistries; 7 | import net.minecraft.world.level.Level; 8 | import net.minecraft.world.level.block.state.BlockState; 9 | import net.minecraft.world.level.chunk.ChunkAccess; 10 | 11 | import java.util.Optional; 12 | 13 | public record SkipChunkHasMarkerBlockSwapPredicate(String s) implements BlockSwapPredicate { 14 | @Override 15 | public boolean test(Level level, ChunkAccess chunk, int localX, int localY, int localZ, BlockState lastState) { 16 | Optional blockSwapLevelChunkData = TrackedDataRegistries.CHUNK.get(BlockSwap.BLOCK_SWAP_CHUNK_DATA, chunk); 17 | if (blockSwapLevelChunkData.isPresent()) { 18 | BlockSwapLevelChunkData chunkData = blockSwapLevelChunkData.get(); 19 | return chunkData.getPlaceHolders().contains(s); 20 | 21 | 22 | } 23 | Optional blockSwapProtoChunkData = TrackedDataRegistries.CHUNK.get(BlockSwap.BLOCK_SWAP_WORLD_GEN_DATA, chunk); 24 | 25 | if (blockSwapProtoChunkData.isPresent()){ 26 | BlockSwapProtoChunkData protoChunkData = blockSwapProtoChunkData.get(); 27 | return protoChunkData.getPlaceHolders().contains(s); 28 | } 29 | 30 | return false; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/common/main/java/dev/corgitaco/blockswap/util/ChunkSectionBlockStateSwapper.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.util; 2 | 3 | import it.unimi.dsi.fastutil.ints.Int2IntMap; 4 | 5 | public interface ChunkSectionBlockStateSwapper { 6 | 7 | void blockSwap$createSwapper(Int2IntMap swapper); 8 | } 9 | -------------------------------------------------------------------------------- /src/fabric/main/java/dev/corgitaco/blockswap/fabric/FabricBlockSwap.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.fabric; 2 | 3 | import dev.corgitaco.blockswap.BlockSwap; 4 | 5 | public class FabricBlockSwap { 6 | public static void initialize() { 7 | BlockSwap.initialize(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/forge/main/java/dev/corgitaco/blockswap/ForgeBlockSwap.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap; 2 | 3 | import net.minecraftforge.fml.common.Mod; 4 | 5 | @Mod(BlockSwap.MOD_ID) 6 | public class ForgeBlockSwap { 7 | 8 | public ForgeBlockSwap() { 9 | BlockSwap.initialize(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/neoforge/main/java/dev/corgitaco/blockswap/neoforge/NeoforgeBlockSwap.java: -------------------------------------------------------------------------------- 1 | package dev.corgitaco.blockswap.neoforge; 2 | 3 | import net.neoforged.fml.common.Mod; 4 | import dev.corgitaco.blockswap.BlockSwap; 5 | 6 | @Mod(BlockSwap.MOD_ID) 7 | public class NeoforgeBlockSwap { 8 | public NeoforgeBlockSwap() { 9 | BlockSwap.initialize(); 10 | } 11 | } 12 | --------------------------------------------------------------------------------