├── .gitattributes ├── .github └── workflows │ └── gradle.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src └── main ├── java └── org │ └── dimdev │ └── jeid │ ├── ASMException.java │ ├── INewBlockStateContainer.java │ ├── INewChunk.java │ ├── JEID.java │ ├── JEIDLoadingPlugin.java │ ├── JEIDTransformer.java │ ├── Utils.java │ ├── mixin │ ├── core │ │ ├── MixinAnvilChunkLoader.java │ │ ├── MixinBlock.java │ │ ├── MixinBlockStateContainer.java │ │ ├── MixinChunk.java │ │ ├── MixinChunkPrimer.java │ │ ├── MixinChunkProviderServer.java │ │ ├── MixinEnchantmentHelper.java │ │ ├── MixinGameData.java │ │ ├── MixinGenLayerVoronoiZoom.java │ │ ├── MixinItemEnchantedBook.java │ │ ├── MixinPacketBuffer.java │ │ ├── MixinSPacketChunkData.java │ │ ├── MixinStatList.java │ │ ├── MixinWorldInfo.java │ │ └── client │ │ │ ├── MixinChunk.java │ │ │ ├── MixinRenderGlobal.java │ │ │ └── MixinWorldSummary.java │ ├── init │ │ └── JEIDMixinLoader.java │ └── modsupport │ │ ├── abyssalcraft │ │ └── MixinBiomeUtil.java │ │ ├── advancedrocketry │ │ ├── MixinBiomeHandler.java │ │ └── MixinPacketBiomeIDChange.java │ │ ├── bewitchment │ │ ├── MixinRitualBiomeShift.java │ │ └── MixinUtils.java │ │ ├── biomesoplenty │ │ ├── MixinBOPCommand.java │ │ └── MixinModBiomes.java │ │ ├── biometweaker │ │ ├── MixinBiomeColorMappings.java │ │ ├── MixinBiomeHelper.java │ │ └── MixinCommandSetBiome.java │ │ ├── bookshelf │ │ └── MixinWorldUtils.java │ │ ├── creepingnether │ │ └── MixinCorruptorAbstract.java │ │ ├── cyclopscore │ │ └── MixinWorldHelpers.java │ │ ├── extrautils2 │ │ ├── MixinBiomeManip.java │ │ └── MixinWorldProviderSpecialDim.java │ │ ├── gaiadimension │ │ └── MixinGenLayerGDRiverMix.java │ │ ├── geographicraft │ │ └── MixinDimensionManager.java │ │ ├── hammercore │ │ └── MixinWorldLocation.java │ │ ├── journeymap │ │ └── MixinChunkMD.java │ │ ├── mystcraft │ │ └── MixinBiomeReplacer.java │ │ ├── thaumcraft │ │ └── MixinUtils.java │ │ ├── thebetweenlands │ │ ├── MixinBlockSpreadingDeath.java │ │ └── MixinGenLayerVoronoiZoomInstanced.java │ │ ├── tofucraft │ │ ├── MixinGenLayerRiverMix.java │ │ └── MixinGenLayerTofuVoronoiZoom.java │ │ ├── tropicraft │ │ └── MixinGenLayerTropiVoronoiZoom.java │ │ ├── twilightforest │ │ ├── MixinBlockTFMagicLogSpecial.java │ │ ├── MixinBlockTFMagicLogSpecial_Old.java │ │ ├── MixinGenLayerTFRiverMix.java │ │ └── TwilightMixinPlugin.java │ │ └── worldedit │ │ └── MixinBaseBlock.java │ └── network │ ├── BiomeArrayMessage.java │ ├── BiomeChangeMessage.java │ └── MessageManager.java └── resources ├── META-INF └── jeid_at.cfg ├── assets └── jeid │ └── logo.png ├── mcmod.info ├── mixins.jeid.core.json ├── mixins.jeid.init.json ├── mixins.jeid.modsupport.json ├── mixins.jeid.twilightforest.json └── pack.mcmeta /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Gradle 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle 3 | 4 | name: Build Mod 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 1.8 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 1.8 23 | - name: Grant execute permission for gradlew 24 | run: chmod +x gradlew 25 | - name: Build with Gradle 26 | run: ./gradlew build 27 | - name: Upload to Release 28 | uses: JasonEtco/upload-to-release@v0.1.1 29 | with: 30 | args: ./build/libs/JustEnoughIDs-*.jar 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.token }} 33 | 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse 2 | eclipse 3 | bin 4 | *.launch 5 | .settings 6 | .metadata 7 | .classpath 8 | .project 9 | 10 | # idea 11 | out 12 | classes 13 | *.ipr 14 | *.iws 15 | *.iml 16 | .idea 17 | 18 | # gradle 19 | build 20 | .gradle 21 | 22 | #Netbeans 23 | .nb-gradle 24 | .nb-gradle-properties 25 | 26 | # other 27 | run 28 | .DS_Store 29 | Thumbs.db 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: openjdk8 3 | 4 | if: tag IS blank 5 | git: 6 | depth: 5 7 | 8 | install: ./gradlew setupCIWorkspace 9 | script: ./gradlew clean build 10 | 11 | before_cache: find $HOME/.gradle/ -name '*.lock' -print -exec rm -f {} \; 12 | cache: 13 | directories: 14 | - $HOME/.gradle/caches/ 15 | - $HOME/.gradle/wrapper/ 16 | 17 | before_deploy: export RELEASE_FILE_LIST=$(ls ./build/libs/* | tr '\n' ', ') 18 | deploy: 19 | skip_cleanup: true 20 | provider: releases 21 | api_key: 22 | secure: ArR73HRTML2+nfEHHcTc824vG3MBgtV2h/naMbpVbgrcD/aRaFvX5RU84BBS0A5KXRs+9/5gkNxffMSmiTD5HlorMh2Qb5eYNs8s43JJ7UlR0hKeVcZb8SbVMooPeNrFbYxQHMgz0VXHYZas4y2vFMd9vwgQOpTcRjnc6wyINkvsR1LtLs5D/w9bKNxz2iv2DNnGZhI/wPrPUkQXzypI6sSG6BbfyzWZ1Z3A2NU2qt6lO5U515/mCwEMVMKxC5BPK+0NCNOMc5oESc/Edmr2XtP2VRVsLI0ouRQniwr8uadoPGFZbj72o/8qGuGInSI0cApi48dS0bT0tUv8AIMseTwxsVNmSAi6PUZ5Mdsoz6yvsezwnD/tyQrCeY5yPZUwLUnwitnPbGcMbv88nioxrbd3nQWRqWNF9v9wdbJLNECfn1jK/iRpv/rw6MYntcMHgENziBM/xq4SQV5vlOsgjnihhGIJ8zQZQ5/RKVKoZj9sOunw7v+OZL6ZeMKIV2/lbwkjeIlTyY0IvZoydG8Lw5RVeMR+vdFULM1dJH1gKLTSl5iEmtX05iSR+LzmqCY+DfOCff7Iyoa+oIN46WuwzxCRz+V7IFUfz+6o4LOQ47vCN6LZvcSlh+qylI9n0YNHO/WMP/KJl9bhcVeCQoe0Zi+lAen9loZa8F2vFdc8DrY= 23 | file_glob: true 24 | file: "{$RELEASE_FILE_LIST}" 25 | on: 26 | repo: DimensionalDevelopment/JustEnoughIDs 27 | branch: master 28 | tags: false 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Dimensional Development 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 2 | 3 | buildscript { 4 | repositories { 5 | maven { url 'https://maven.minecraftforge.net' } 6 | maven { url "https://plugins.gradle.org/m2/" } 7 | maven { url "https://repo.spongepowered.org/repository/maven-public" } 8 | mavenCentral() 9 | } 10 | dependencies { 11 | classpath "gradle.plugin.com.github.johnrengelman:shadow:7.1.1" 12 | classpath 'net.minecraftforge.gradle:ForgeGradle:5.1.+' 13 | classpath "org.spongepowered:mixingradle:0.7-SNAPSHOT" 14 | } 15 | } 16 | 17 | apply plugin: 'net.minecraftforge.gradle' 18 | // Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. 19 | apply plugin: 'eclipse' 20 | apply plugin: 'maven-publish' 21 | apply plugin: "com.github.johnrengelman.shadow" 22 | apply plugin: 'org.spongepowered.mixin' 23 | 24 | def travisBuildNumber = System.getenv("TRAVIS_BUILD_NUMBER") 25 | def versionSuffix = travisBuildNumber != null ? travisBuildNumber : "SNAPSHOT" 26 | 27 | version "1.0.4-$versionSuffix" 28 | group "org.dimdev.jeid" 29 | archivesBaseName = "JustEnoughIDs" 30 | 31 | sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. 32 | 33 | minecraft { 34 | // The mappings can be changed at any time, and must be in the following format. 35 | // snapshot_YYYYMMDD Snapshot are built nightly. 36 | // stable_# Stables are built at the discretion of the MCP team. 37 | // Use non-default mappings at your own risk. they may not always work. 38 | // Simply re-run your setup task after changing the mappings to update your workspace. 39 | mappings channel: 'stable', version: '39-1.12' 40 | 41 | accessTransformer = file('src/main/resources/META-INF/jeid_at.cfg') 42 | 43 | // Default run configurations. 44 | // These can be tweaked, removed, or duplicated as needed. 45 | runs { 46 | client { 47 | 48 | jvmArg "-Dfml.coreMods.load=org.dimdev.jeid.JEIDLoadingPlugin" 49 | jvmArg "-Dmixin.hotSwap=true" 50 | jvmArg "-Dmixin.checks.interfaces=true" 51 | 52 | workingDirectory project.file('run') 53 | 54 | // Recommended logging data for a userdev environment 55 | property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' 56 | 57 | // Recommended logging level for the console 58 | property 'forge.logging.console.level', 'debug' 59 | } 60 | 61 | server { 62 | 63 | jvmArg "-Dfml.coreMods.load=org.dimdev.jeid.JEIDLoadingPlugin" 64 | jvmArg "-Dmixin.hotSwap=true" 65 | jvmArg "-Dmixin.checks.interfaces=true" 66 | 67 | // Recommended logging data for a userdev environment 68 | property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' 69 | 70 | // Recommended logging level for the console 71 | property 'forge.logging.console.level', 'debug' 72 | } 73 | } 74 | } 75 | 76 | configurations { 77 | compileJar { 78 | implementation.extendsFrom(compileJar) 79 | } 80 | } 81 | 82 | repositories { 83 | maven { url "https://repo.spongepowered.org/maven" } 84 | maven { 85 | url "https://cursemaven.com" 86 | content { 87 | includeGroup "curse.maven" 88 | } 89 | metadataSources { 90 | artifact() 91 | } 92 | } 93 | } 94 | 95 | dependencies { 96 | // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed 97 | // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. 98 | // The userdev artifact is a special name and will get all sorts of transformations applied to it. 99 | minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2860' 100 | 101 | annotationProcessor("org.spongepowered:mixin:0.8.3:processor") 102 | compileJar("org.spongepowered:mixin:0.8.3") { 103 | exclude module: "asm-commons" 104 | exclude module: "asm-tree" 105 | exclude module: "launchwrapper" 106 | exclude module: "guava" 107 | exclude module: "log4j-core" 108 | exclude module: "gson" 109 | exclude module: "commons-io" 110 | } 111 | compileOnly fg.deobf( "curse.maven:BiomesOPlenty-220318:2842510" ) 112 | compileOnly fg.deobf( "curse.maven:twilightforest-227639:3051450" ) 113 | compileOnly fg.deobf( "curse.maven:Thaumcraft-223628:2629023" ) 114 | compileOnly fg.deobf( "curse.maven:AbyssalCraft-53686:3425234" ) 115 | compileOnly fg.deobf( "curse.maven:Creeping+Nether-268104:2655432" ) 116 | compileOnly fg.deobf( "curse.maven:GeographiCraft-76544:2497541" ) 117 | compileOnly fg.deobf( "curse.maven:mystcraft-224599:2958490" ) 118 | compileOnly fg.deobf( "curse.maven:HammerCore-247401:3366814" ) 119 | compileOnly fg.deobf( "curse.maven:AdvancedRocketry-236542:3015079" ) 120 | compileOnly fg.deobf( "curse.maven:LibVulpes-236541:3434864" ) 121 | compileOnly fg.deobf( "curse.maven:worldedit-225608:2941712" ) 122 | compileOnly fg.deobf( "curse.maven:journeymap-32274:2916002" ) 123 | compileOnly fg.deobf( "curse.maven:Bookshelf-228525:2836960" ) 124 | compileOnly fg.deobf( "curse.maven:CyclopsCore-232758:3159497" ) 125 | compileOnly fg.deobf( "curse.maven:extrautils2-225561:2678374" ) 126 | compileOnly fg.deobf( "curse.maven:TheBetweenlands-243363:3248202" ) 127 | compileOnly fg.deobf( "curse.maven:TofuCraftReload-317469:3115668" ) 128 | compileOnly fg.deobf( "curse.maven:tropicraft-254794:2713918" ) 129 | compileOnly fg.deobf( "curse.maven:gaiadimension-302529:2724738" ) 130 | compileOnly fg.deobf( "curse.maven:BiomeTweaker-228895:3112142" ) 131 | compileOnly fg.deobf( "curse.maven:baubles-227083:2518667" ) 132 | compileOnly fg.deobf( "curse.maven:Patchouli-306770:3162874" ) 133 | compileOnly fg.deobf( "curse.maven:bewitchment-285439:3256343" ) 134 | } 135 | 136 | // Example for how to get properties into the manifest for reading by the runtime.. 137 | jar { 138 | manifest { 139 | attributes([ 140 | "FMLCorePluginContainsFMLMod": "true", 141 | "TweakClass": "org.spongepowered.asm.launch.MixinTweaker", 142 | "FMLCorePlugin": "org.dimdev.jeid.JEIDLoadingPlugin", 143 | "ForceLoadAsMod": "true", 144 | "FMLAT": "jeid_at.cfg" 145 | ]) 146 | } 147 | } 148 | 149 | // Example configuration to allow publishing using the maven-publish task 150 | // This is the preferred method to reobfuscate your jar file 151 | jar.finalizedBy('reobfJar') 152 | // However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing 153 | //publish.dependsOn('reobfJar') 154 | 155 | java { 156 | withSourcesJar() 157 | } 158 | 159 | processResources { 160 | duplicatesStrategy(DuplicatesStrategy.INCLUDE) 161 | from (sourceSets.main.resources.srcDirs) { 162 | include("mcmod.info") 163 | expand("version": version) 164 | } 165 | } 166 | 167 | publishing { 168 | publications { 169 | mavenJava(MavenPublication) { 170 | artifact jar 171 | } 172 | } 173 | repositories { 174 | maven { 175 | url "file:///${project.projectDir}/mcmodsrepo" 176 | } 177 | 178 | } 179 | } 180 | 181 | mixin { 182 | add sourceSets.main, "mixins.jeid.refmap.json" 183 | disableAnnotationProcessorCheck() 184 | } 185 | 186 | shadowJar { 187 | archiveClassifier.set(null) 188 | configurations = [project.configurations.compileJar] 189 | } 190 | 191 | task thinShadowJar(type: ShadowJar) { 192 | archiveClassifier.set("thin") 193 | configurations = [project.configurations.compileJar] 194 | relocators = shadowJar.relocators 195 | 196 | dependencies { 197 | exclude(dependency("org.spongepowered:mixin")) 198 | } 199 | 200 | manifest { 201 | inheritFrom jar.manifest 202 | } 203 | 204 | from sourceSets.main.output 205 | } 206 | 207 | artifacts { 208 | archives shadowJar 209 | archives sourcesJar 210 | archives thinShadowJar 211 | } 212 | 213 | reobf { 214 | shadowJar {} 215 | thinShadowJar {} 216 | } 217 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Sets default memory used for gradle commands. Can be overridden by user or command line properties. 2 | # This is required to provide enough memory for the Minecraft decompilation process. 3 | org.gradle.jvmargs=-Xmx7G 4 | org.gradle.daemon=false -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionalDevelopment/JustEnoughIDs/4d7f1fc4ff3afd965e698f98f998c1d5072518db/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-7.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/ASMException.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid; 2 | 3 | import org.objectweb.asm.tree.*; 4 | 5 | import java.util.Iterator; 6 | 7 | public class ASMException extends RuntimeException { 8 | private static final long serialVersionUID = -8581611883691404427L; 9 | 10 | public ASMException(String message) { 11 | super("JustEnoughIDs - Class transformation error\n"+message); 12 | } 13 | 14 | public ASMException(String message, ClassNode node) { 15 | this(message+"\n"+getStringDescriptor(node)); 16 | } 17 | 18 | public ASMException(String message, MethodNode node) { 19 | this(message+"\n"+getStringDescriptor(node)); 20 | } 21 | 22 | private static String getStringDescriptor(MethodNode node) { 23 | StringBuilder sb = new StringBuilder(); 24 | Iterator i = node.instructions.iterator(); 25 | while (i.hasNext()) { 26 | AbstractInsnNode n = i.next(); 27 | sb.append("["+n.getOpcode()+"] - "+getInsnDesc(n)+"\n"); 28 | } 29 | return sb.toString(); 30 | } 31 | 32 | private static String getInsnDesc(AbstractInsnNode n) { 33 | if (n instanceof LdcInsnNode) { 34 | return "LDC - "+((LdcInsnNode)n).cst.toString(); 35 | } 36 | if (n instanceof LabelNode) { 37 | return "Label - "+((LabelNode)n).getLabel().toString(); 38 | } 39 | if (n instanceof LineNumberNode) { 40 | return "Line - "+((LineNumberNode)n).line; 41 | } 42 | if (n instanceof IntInsnNode) { 43 | return "Int - "+((IntInsnNode)n).operand; 44 | } 45 | if (n instanceof MethodInsnNode) { 46 | MethodInsnNode m = (MethodInsnNode)n; 47 | return "Method - "+m.name+", "+m.desc+", "+m.owner; 48 | } 49 | return n.getClass().getName(); 50 | } 51 | 52 | private static String getStringDescriptor(ClassNode node) { 53 | StringBuilder sb = new StringBuilder(); 54 | node.methods.forEach(m -> sb.append(m.name+": "+m.desc+"\n")); 55 | return sb.toString(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/INewBlockStateContainer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid; 2 | 3 | public interface INewBlockStateContainer { 4 | void setTemporaryPalette(int[] temporaryPalette); 5 | int[] getTemporaryPalette(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/INewChunk.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid; 2 | 3 | public interface INewChunk { 4 | int[] getIntBiomeArray(); 5 | void setIntBiomeArray(int[] intBiomeArray); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/JEID.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid; 2 | 3 | import net.minecraft.block.Block; 4 | import net.minecraft.block.material.Material; 5 | import net.minecraft.creativetab.CreativeTabs; 6 | import net.minecraft.enchantment.Enchantment; 7 | import net.minecraft.enchantment.EnumEnchantmentType; 8 | import net.minecraft.inventory.EntityEquipmentSlot; 9 | import net.minecraft.item.Item; 10 | import net.minecraft.item.ItemBlock; 11 | import net.minecraft.potion.Potion; 12 | import net.minecraft.potion.PotionEffect; 13 | import net.minecraft.potion.PotionType; 14 | import net.minecraft.util.ResourceLocation; 15 | import net.minecraft.world.biome.Biome; 16 | import net.minecraft.world.biome.BiomeVoid; 17 | import net.minecraftforge.fml.common.Mod; 18 | import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; 19 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 20 | import net.minecraftforge.fml.common.registry.GameRegistry; 21 | import net.minecraftforge.registries.IForgeRegistry; 22 | import org.dimdev.jeid.network.MessageManager; 23 | 24 | import java.util.Random; 25 | 26 | @Mod(modid = "jeid", 27 | name = "JustEnoughIDs", 28 | updateJSON = "https://gist.githubusercontent.com/Runemoro/67b1d8d31af58e9d35410ef60b2017c3/raw/1fe08a6c45a1f481a8a2a8c71e52d4245dcb7713/jeid_update.json") 29 | public class JEID { 30 | private static final boolean DEBUG_BLOCK_IDS = false; 31 | private static final boolean DEBUG_ITEM_IDS = false; 32 | private static final boolean DEBUG_BIOME_IDS = false; 33 | private static final boolean DEBUG_POTION_IDS = false; 34 | private static final boolean DEBUG_ENCHANT_IDS = false; 35 | public static final Biome errorBiome = new BiomeVoid(new Biome.BiomeProperties("A mod doesn't support extended biome IDs -- report to JEID")) 36 | .setRegistryName("jeid:error_biome"); 37 | 38 | 39 | @Mod.EventHandler 40 | public void onPreInit(FMLPreInitializationEvent event) { 41 | // Register messages 42 | MessageManager.init(); 43 | 44 | // Error Biome Registration 45 | GameRegistry.findRegistry(Biome.class).register(errorBiome); 46 | 47 | // Debug code 48 | if (DEBUG_BLOCK_IDS) { 49 | IForgeRegistry blockRegistry = GameRegistry.findRegistry(Block.class); 50 | IForgeRegistry itemRegistry = GameRegistry.findRegistry(Item.class); 51 | for (int i = 0; i < 5000; i++) { 52 | Block block = new Block(Material.GROUND) 53 | .setCreativeTab(CreativeTabs.BUILDING_BLOCKS) 54 | .setRegistryName(new ResourceLocation("jeid:block_" + i)); 55 | 56 | blockRegistry.register(block); 57 | itemRegistry.register(new ItemBlock(block).setRegistryName(new ResourceLocation("jeid:block_" + i))); 58 | } 59 | } 60 | 61 | if (DEBUG_ITEM_IDS) { 62 | IForgeRegistry itemRegistry = GameRegistry.findRegistry(Item.class); 63 | for (int i = 0; i < 40000; i++) { 64 | Item item = new Item() 65 | .setCreativeTab(CreativeTabs.FOOD) 66 | .setRegistryName(new ResourceLocation("jeid:item_" + i)); 67 | 68 | itemRegistry.register(item); 69 | } 70 | } 71 | 72 | if (DEBUG_BIOME_IDS) { 73 | IForgeRegistry biomeRegistry = GameRegistry.findRegistry(Biome.class); 74 | for (int i = 0; i < 300; i++) { 75 | Biome biome = new Biome(new Biome.BiomeProperties("Biome " + i)) {} 76 | .setRegistryName(new ResourceLocation("jeid:biome_" + i)); 77 | 78 | biomeRegistry.register(biome); 79 | } 80 | } 81 | 82 | if (DEBUG_POTION_IDS) { 83 | IForgeRegistry potionRegistry = GameRegistry.findRegistry(Potion.class); 84 | IForgeRegistry potionTypeRegistry = GameRegistry.findRegistry(PotionType.class); 85 | for (int i = 0; i < 300; i++) { 86 | Potion potion = new PotionTest(i).setRegistryName(new ResourceLocation("jeid:potion_" + i)); 87 | potionRegistry.register(potion); 88 | } 89 | 90 | for (int i = 0; i < 300; i++) { 91 | PotionType pt = new PotionType(new PotionEffect(Potion.REGISTRY.getObject(new ResourceLocation("jeid:potion_" + i)), 92 | 2000, 93 | 0, 94 | false, 95 | true)); 96 | pt.setRegistryName(new ResourceLocation("jeid:potiontype_"+i)); 97 | potionTypeRegistry.register(pt); 98 | } 99 | } 100 | 101 | if (DEBUG_ENCHANT_IDS) { 102 | IForgeRegistry enchantRegistry = GameRegistry.findRegistry(Enchantment.class); 103 | for (int i = 0; i < Short.MAX_VALUE; i++) { 104 | Enchantment ench = new EnchantTest(i).setRegistryName(new ResourceLocation("jeid:enchant_"+i)); 105 | 106 | enchantRegistry.register(ench); 107 | } 108 | } 109 | } 110 | 111 | @Mod.EventHandler 112 | public void postInit(FMLPostInitializationEvent e) { 113 | JEIDTransformer.REGISTRY = net.minecraftforge.registries.GameData.getWrapper(Potion.class); 114 | } 115 | 116 | public static class PotionTest extends Potion { 117 | 118 | private static final Random r = new Random(); 119 | private String nm; 120 | 121 | protected PotionTest(int id) { 122 | super(false, 0xFFFFFF & r.nextInt(Integer.MAX_VALUE)); 123 | nm = "Test Potion #"+id; 124 | } 125 | 126 | @Override 127 | public String getName() { 128 | return nm; 129 | } 130 | } 131 | 132 | public static class EnchantTest extends Enchantment { 133 | 134 | public EnchantTest(int i) 135 | { 136 | super(Rarity.COMMON, EnumEnchantmentType.BOW, new EntityEquipmentSlot[EntityEquipmentSlot.CHEST.getIndex()]); 137 | this.setName("Test Enchantment #"+i); 138 | } 139 | 140 | } 141 | } -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/JEIDLoadingPlugin.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid; 2 | 3 | import net.minecraftforge.common.ForgeVersion; 4 | import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; 5 | import org.spongepowered.asm.launch.MixinBootstrap; 6 | import org.spongepowered.asm.mixin.Mixins; 7 | 8 | import javax.annotation.Nullable; 9 | import java.util.Map; 10 | 11 | @IFMLLoadingPlugin.MCVersion(ForgeVersion.mcVersion) 12 | @IFMLLoadingPlugin.SortingIndex(-7500) 13 | @IFMLLoadingPlugin.Name("JustEnoughIDs Extension Plugin") 14 | //@IFMLLoadingPlugin.TransformerExclusions("org.dimdev.jeid.") 15 | public class JEIDLoadingPlugin implements IFMLLoadingPlugin { 16 | 17 | public JEIDLoadingPlugin() { 18 | MixinBootstrap.init(); 19 | Utils.LOGGER.info("Initializing JustEnoughIDs core mixins"); 20 | Mixins.addConfiguration("mixins.jeid.core.json"); 21 | Utils.LOGGER.info("Initializing JustEnoughIDs initialization mixins"); 22 | Mixins.addConfiguration("mixins.jeid.init.json"); 23 | } 24 | 25 | @Override public String[] getASMTransformerClass() { Obf.loadData(); return new String[]{ "org.dimdev.jeid.JEIDTransformer" }; } 26 | @Override public String getModContainerClass() { return null; } 27 | @Nullable @Override public String getSetupClass() { return null; } 28 | @Override public void injectData(Map data) {} 29 | @Override public String getAccessTransformerClass() { return null; } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/JEIDTransformer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid; 2 | 3 | import net.minecraft.launchwrapper.IClassTransformer; 4 | import net.minecraft.launchwrapper.Launch; 5 | import net.minecraft.potion.Potion; 6 | import net.minecraft.potion.PotionEffect; 7 | import net.minecraft.util.ResourceLocation; 8 | import net.minecraft.util.registry.RegistryNamespaced; 9 | import net.minecraftforge.fml.relauncher.FMLLaunchHandler; 10 | import org.objectweb.asm.ClassReader; 11 | import org.objectweb.asm.ClassWriter; 12 | import org.objectweb.asm.Opcodes; 13 | import org.objectweb.asm.Type; 14 | import org.objectweb.asm.tree.*; 15 | 16 | import java.util.Iterator; 17 | import java.util.function.Predicate; 18 | 19 | /** 20 | * This class was borrowed from Zabi94's MaxPotionIDExtender 21 | * under MIT License and with full help of Zabi. All credit in this class goes to Zabi 22 | * and his incredible work on figuring out how to make this work and helping out. 23 | * 24 | * https://github.com/zabi94/MaxPotionIDExtender 25 | */ 26 | public class JEIDTransformer implements IClassTransformer { 27 | 28 | public static RegistryNamespaced REGISTRY; 29 | 30 | @Override 31 | public byte[] transform(String name, String transformedName, byte[] basicClass) { 32 | if (transformedName.equals("net.minecraft.client.network.NetHandlerPlayClient")) { 33 | return transformNetHandlerPlayClient(basicClass); 34 | } 35 | if (transformedName.equals("net.minecraft.potion.PotionEffect")) { 36 | return transformPotionEffect(basicClass); 37 | } 38 | if (transformedName.equals("net.minecraft.network.play.server.SPacketEntityEffect")) { 39 | return transformSPacketEntityEffect(basicClass); 40 | } 41 | if (transformedName.equals("net.minecraft.network.play.server.SPacketRemoveEntityEffect")) { 42 | return transformSPacketRemoveEntityEffect(basicClass); 43 | } 44 | if (transformedName.equals("net.minecraft.item.ItemStack")) { 45 | return transformItemStack(basicClass); 46 | } 47 | if (transformedName.equals("net.minecraft.nbt.NBTTagCompound")) { 48 | ClassReader cr = new ClassReader(basicClass); 49 | ClassNode cn = new ClassNode(); 50 | cr.accept(cn, 0); 51 | if (!cn.name.equals(Obf.NBTTagCompound)) { 52 | throw new ASMException("The class NBTTagCompound has broken mappings, should be "+cn.name); 53 | } 54 | } 55 | if (transformedName.equals("net.minecraft.network.PacketBuffer")) { 56 | ClassReader cr = new ClassReader(basicClass); 57 | ClassNode cn = new ClassNode(); 58 | cr.accept(cn, 0); 59 | if (!cn.name.equals(Obf.PacketBuffer)) { 60 | throw new ASMException("The class PacketBuffer has broken mappings, should be "+cn.name); 61 | } 62 | } 63 | return basicClass; 64 | } 65 | 66 | private static MethodNode locateMethod(ClassNode cn, String desc, String... namesIn) { 67 | return cn.methods.stream() 68 | .filter(n -> n.desc.equals(desc) && anyMatch(namesIn, n.name)) 69 | .findAny().orElseThrow(() -> new ASMException(getNames(namesIn) +": "+desc+" cannot be found in "+cn.name, cn)); 70 | } 71 | 72 | private static boolean anyMatch(String[] pool, String match) { 73 | for (String s:pool) { 74 | if (s.equals(match)) { 75 | return true; 76 | } 77 | } 78 | return false; 79 | } 80 | 81 | private static String getNames(String[] pool) { 82 | StringBuilder sb = new StringBuilder(); 83 | for (String s:pool) { 84 | sb.append(s); 85 | sb.append(" "); 86 | } 87 | return sb.toString().trim(); 88 | } 89 | 90 | private static AbstractInsnNode locateTargetInsn(MethodNode mn, Predicate filter) { 91 | AbstractInsnNode target = null; 92 | Iterator i = mn.instructions.iterator(); 93 | while (i.hasNext() && target == null) { 94 | AbstractInsnNode n = i.next(); 95 | if (filter.test(n)) { 96 | target = n; 97 | } 98 | } 99 | if (target==null) { 100 | throw new ASMException("Can't locate target instruction in "+mn.name, mn); 101 | } 102 | return target; 103 | } 104 | 105 | private byte[] transformItemStack(byte[] basicClass) { 106 | ClassReader cr = new ClassReader(basicClass); 107 | ClassNode cn = new ClassNode(); 108 | cr.accept(cn, 0); 109 | 110 | if (!cn.name.equals(Obf.ItemStack)) { 111 | throw new ASMException("The class ItemStack has broken mappings, should be "+cn.name); 112 | } 113 | 114 | String descAddEnch = "(L"+Obf.Enchantment+";I)V"; 115 | MethodNode mn = locateMethod(cn, descAddEnch, "addEnchantment", "func_77966_a", "a"); 116 | 117 | String setIntegerName = Obf.isDeobf() ? "setInteger" : "func_74768_a"; 118 | 119 | mn.instructions.remove(locateTargetInsn(mn, n -> n.getOpcode()==Opcodes.I2S)); 120 | AbstractInsnNode target2 = locateTargetInsn(mn, n -> n.getOpcode()==Opcodes.INVOKEVIRTUAL && n.getPrevious().getPrevious().getPrevious().getOpcode()==Opcodes.LDC && ((LdcInsnNode)n.getPrevious().getPrevious().getPrevious()).cst.toString().equals("id")); 121 | mn.instructions.insertBefore(target2, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Obf.NBTTagCompound, setIntegerName, "(Ljava/lang/String;I)V", false)); 122 | mn.instructions.remove(target2); 123 | 124 | 125 | String descr = "(L"+Obf.EntityPlayer+";L"+Obf.ITooltipFlag+";)Ljava/util/List;"; 126 | String getIntegerName = Obf.isDeobf()?"getInteger":"func_74762_e"; 127 | 128 | if (FMLLaunchHandler.side().isClient()) { 129 | MethodNode mn2 = locateMethod(cn, descr, "func_82840_a", "getTooltip", "a"); 130 | AbstractInsnNode target = locateTargetInsn(mn2, n -> n.getOpcode() == Opcodes.INVOKEVIRTUAL && n.getPrevious().getOpcode() == Opcodes.LDC && ((LdcInsnNode) n.getPrevious()).cst.toString().equals("id")); 131 | mn.instructions.insertBefore(target, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Obf.NBTTagCompound, getIntegerName, "(Ljava/lang/String;)I", false)); 132 | mn.instructions.remove(target); 133 | } 134 | 135 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); 136 | cn.accept(cw); 137 | return cw.toByteArray(); 138 | } 139 | 140 | private byte[] transformSPacketRemoveEntityEffect(byte[] basicClass) { 141 | ClassReader cr = new ClassReader(basicClass); 142 | ClassNode cn = new ClassNode(); 143 | cr.accept(cn, 0); 144 | String descriptors = "(L"+Obf.PacketBuffer+";)V"; 145 | MethodNode rpd = locateMethod(cn, descriptors, "readPacketData", "a"); 146 | AbstractInsnNode target = locateTargetInsn(rpd, n -> n.getOpcode() == Opcodes.INVOKEVIRTUAL && ((MethodInsnNode)n).name.equals("readUnsignedByte")); 147 | rpd.instructions.insert(target, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Obf.PacketBuffer, "readInt", "()I", false)); 148 | rpd.instructions.remove(target); 149 | 150 | MethodNode wpd = locateMethod(cn, descriptors, "writePacketData", "b"); 151 | target = locateTargetInsn(wpd, n -> n.getOpcode() == Opcodes.INVOKEVIRTUAL && ((MethodInsnNode)n).name.equals("writeByte")); 152 | wpd.instructions.insert(target, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Obf.PacketBuffer, "writeInt", "(I)Lio/netty/buffer/ByteBuf;", false)); 153 | wpd.instructions.remove(target); 154 | 155 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); 156 | cn.accept(cw); 157 | return cw.toByteArray(); 158 | } 159 | 160 | private byte[] transformSPacketEntityEffect(byte[] basicClass) { 161 | ClassReader cr = new ClassReader(basicClass); 162 | ClassNode cn = new ClassNode(); 163 | cr.accept(cn, 0); 164 | 165 | if (!Obf.SPacketEntityEffect.equals(cn.name)) { 166 | //throw new ASMException("Mapping mismatch! SPacketEntityEffect is "+cn.name+", not "+Obf.SPacketEntityEffect); 167 | } 168 | 169 | //Adding a new field, int effectInt 170 | cn.fields.add(new FieldNode(Opcodes.ACC_PUBLIC, "effectInt", "I", null, 0)); 171 | 172 | //Initialize this field in the constructor 173 | MethodNode mn_init = locateMethod(cn, "(IL"+Obf.PotionEffect+";)V", "", ""); 174 | Iterator i = mn_init.instructions.iterator(); 175 | AbstractInsnNode targetNode = null; 176 | int line = 0; 177 | while (i.hasNext() && targetNode == null) { 178 | AbstractInsnNode node = i.next(); 179 | if (node instanceof LineNumberNode) { 180 | if (line == 1) { 181 | targetNode = node; 182 | } 183 | line++; 184 | } 185 | } 186 | 187 | if (targetNode == null) { 188 | throw new RuntimeException("Can't find target node for SPacketEntityEffect constructor"); 189 | } 190 | 191 | //These are reversed, they get pushed down the stack 192 | mn_init.instructions.insert(targetNode, new FieldInsnNode(Opcodes.PUTFIELD, Obf.SPacketEntityEffect, "effectInt", "I")); 193 | mn_init.instructions.insert(targetNode, new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(this.getClass()), "getIdFromPotEffect", "(L"+Obf.PotionEffect+";)I", false)); 194 | mn_init.instructions.insert(targetNode, new VarInsnNode(Opcodes.ALOAD, 2)); 195 | mn_init.instructions.insert(targetNode, new VarInsnNode(Opcodes.ALOAD, 0)); 196 | 197 | MethodNode mn_empty_init = locateMethod(cn, "()V", "", ""); 198 | 199 | AbstractInsnNode tgt = locateTargetInsn(mn_empty_init, n -> n.getOpcode()==Opcodes.RETURN); 200 | mn_empty_init.instructions.insertBefore(tgt, new VarInsnNode(Opcodes.ALOAD, 0)); 201 | mn_empty_init.instructions.insertBefore(tgt, new LdcInsnNode(0)); 202 | mn_empty_init.instructions.insertBefore(tgt, new FieldInsnNode(Opcodes.PUTFIELD, Obf.SPacketEntityEffect, "effectInt", "I")); 203 | 204 | //Patch readPacketData 205 | MethodNode mn_readPacket = locateMethod(cn, "(L"+Obf.PacketBuffer+";)V", "readPacketData", "a"); 206 | String readVarInt_name = (Obf.isDeobf()?"readVarInt":"g"); 207 | 208 | AbstractInsnNode target = locateTargetInsn(mn_readPacket, n -> n.getOpcode()==Opcodes.RETURN).getPrevious().getPrevious(); 209 | mn_readPacket.instructions.insertBefore(target, new VarInsnNode(Opcodes.ALOAD, 0)); 210 | mn_readPacket.instructions.insertBefore(target, new VarInsnNode(Opcodes.ALOAD, 1)); 211 | mn_readPacket.instructions.insertBefore(target, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Obf.PacketBuffer, readVarInt_name, "()I", false)); 212 | mn_readPacket.instructions.insertBefore(target, new FieldInsnNode(Opcodes.PUTFIELD, Obf.SPacketEntityEffect, "effectInt", "I")); 213 | 214 | //Patch writePacketData 215 | MethodNode mn_writePacket = locateMethod(cn, "(L"+Obf.PacketBuffer+";)V", "writePacketData", "b"); 216 | String writeVarInt_name = (Obf.isDeobf()?"writeVarInt":"d"); 217 | AbstractInsnNode wp_target = locateTargetInsn(mn_writePacket, n -> n.getOpcode()==Opcodes.RETURN).getPrevious().getPrevious(); 218 | 219 | mn_writePacket.instructions.insertBefore(wp_target, new VarInsnNode(Opcodes.ALOAD, 1)); 220 | mn_writePacket.instructions.insertBefore(wp_target, new VarInsnNode(Opcodes.ALOAD, 0)); 221 | mn_writePacket.instructions.insertBefore(wp_target, new FieldInsnNode(Opcodes.GETFIELD, Obf.SPacketEntityEffect, "effectInt", "I")); 222 | mn_writePacket.instructions.insertBefore(wp_target, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Obf.PacketBuffer, writeVarInt_name, "(I)L"+Obf.PacketBuffer+";", false)); 223 | mn_writePacket.instructions.insertBefore(wp_target, new InsnNode(Opcodes.POP)); 224 | 225 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); 226 | cn.accept(cw); 227 | return cw.toByteArray(); 228 | } 229 | 230 | private byte[] transformPotionEffect(byte[] basicClass) { 231 | ClassReader cr = new ClassReader(basicClass); 232 | ClassNode cn = new ClassNode(); 233 | cr.accept(cn, 0); 234 | 235 | if (!cn.name.equals(Obf.PotionEffect)) { 236 | throw new RuntimeException("Mapping mismatch! PotionEffect is "+cn.name+", not "+Obf.PotionEffect); 237 | } 238 | 239 | MethodNode mn = locateMethod(cn, "(L"+Obf.NBTTagCompound+";)L"+Obf.NBTTagCompound+";", "writeCustomPotionEffectToNBT", "a"); 240 | AbstractInsnNode ant = locateTargetInsn(mn, n -> n.getOpcode() == Opcodes.I2B); 241 | String mname = (Obf.isDeobf()?"setInteger":"a"); 242 | MethodInsnNode call = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Obf.NBTTagCompound, mname, "(Ljava/lang/String;I)V", false); 243 | mn.instructions.remove(ant.getNext()); 244 | mn.instructions.insert(ant, call); 245 | mn.instructions.remove(ant); 246 | 247 | 248 | MethodNode mn2 = locateMethod(cn, "(L"+Obf.NBTTagCompound+";)L"+Obf.PotionEffect+";", "readCustomPotionEffectFromNBT", "b"); 249 | AbstractInsnNode ant2 = locateTargetInsn(mn2, n -> n.getOpcode() == Opcodes.INVOKEVIRTUAL); 250 | 251 | String name2 = (Obf.isDeobf()?"getInteger":"h"); 252 | 253 | mn2.instructions.remove(ant2.getNext()); 254 | mn2.instructions.remove(ant2.getNext()); 255 | mn2.instructions.insert(ant2, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Obf.NBTTagCompound, name2, "(Ljava/lang/String;)I", false)); 256 | mn2.instructions.remove(ant2); 257 | 258 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); 259 | cn.accept(cw); 260 | return cw.toByteArray(); 261 | } 262 | 263 | private byte[] transformNetHandlerPlayClient(byte[] basicClass) { 264 | ClassReader cr = new ClassReader(basicClass); 265 | ClassNode cn = new ClassNode(); 266 | cr.accept(cn, 0); 267 | 268 | MethodNode mn = locateMethod(cn, "(L"+Obf.SPacketEntityEffect+";)V", "handleEntityEffect", "a"); 269 | AbstractInsnNode target = locateTargetInsn(mn, n -> n.getOpcode()==Opcodes.SIPUSH); 270 | mn.instructions.remove(target.getPrevious()); 271 | mn.instructions.remove(target.getNext()); 272 | mn.instructions.insertBefore(target, new FieldInsnNode(Opcodes.GETFIELD, Obf.SPacketEntityEffect, "effectInt", "I")); 273 | mn.instructions.remove(target); 274 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); 275 | cn.accept(cw); 276 | return cw.toByteArray(); 277 | } 278 | 279 | public static int getIdFromPotEffect(PotionEffect pe) { return REGISTRY.getIDForObject(pe.getPotion()); } 280 | } 281 | 282 | class Obf { 283 | 284 | 285 | public static boolean isPotionClass(String s) { 286 | if (s.endsWith(";")) { 287 | s = s.substring(1, s.length()-1); 288 | } 289 | return s.equals(Type.getInternalName(Potion.class)) || s.equals("uz"); 290 | } 291 | 292 | public static boolean isDeobf() { 293 | return (boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment"); 294 | } 295 | 296 | public static void loadData() { 297 | if ((boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment")) { 298 | NBTTagCompound = "net/minecraft/nbt/NBTTagCompound"; 299 | PotionEffect ="net/minecraft/potion/PotionEffect"; 300 | SPacketEntityEffect = "net/minecraft/network/play/server/SPacketEntityEffect"; 301 | PacketBuffer = "net/minecraft/network/PacketBuffer"; 302 | ItemStack = "net/minecraft/item/ItemStack"; 303 | ITooltipFlag = "net/minecraft/client/util/ITooltipFlag"; 304 | Enchantment = "net/minecraft/enchantment/Enchantment"; 305 | EntityPlayer = "net/minecraft/entity/player/EntityPlayer"; 306 | } else { 307 | NBTTagCompound = "fy"; 308 | PotionEffect = "va"; 309 | SPacketEntityEffect = "kw"; 310 | PacketBuffer = "gy"; 311 | ItemStack = "aip"; 312 | ITooltipFlag = "akb"; 313 | Enchantment = "alk"; 314 | EntityPlayer = "aed"; 315 | } 316 | } 317 | 318 | public static String NBTTagCompound; 319 | public static String PotionEffect; 320 | public static String SPacketEntityEffect; 321 | public static String PacketBuffer; 322 | public static String ItemStack; 323 | public static String ITooltipFlag; 324 | public static String Enchantment; 325 | public static String EntityPlayer; 326 | } 327 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/Utils.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | 6 | public class Utils { 7 | /** 8 | * I Know this looks stupid and it's a single class for a logger, but deal with 9 | * it you nerds. 10 | * - Zombie 11 | */ 12 | public static Logger LOGGER = LogManager.getLogger("JustEnoughIDs"); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinAnvilChunkLoader.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import net.minecraft.nbt.NBTTagCompound; 4 | import net.minecraft.nbt.NBTTagList; 5 | import net.minecraft.world.World; 6 | import net.minecraft.world.chunk.Chunk; 7 | import net.minecraft.world.chunk.NibbleArray; 8 | import net.minecraft.world.chunk.storage.AnvilChunkLoader; 9 | import net.minecraft.world.chunk.storage.ExtendedBlockStorage; 10 | import org.dimdev.jeid.INewBlockStateContainer; 11 | import org.dimdev.jeid.INewChunk; 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.Redirect; 16 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 17 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 18 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture; 19 | 20 | @Mixin(AnvilChunkLoader.class) 21 | public class MixinAnvilChunkLoader { 22 | /** @reason Read palette from NBT for JustEnoughIDs BlockStateContainers. */ 23 | @Inject(method = "readChunkFromNBT", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/chunk/storage/ExtendedBlockStorage;(IZ)V", shift = At.Shift.BY, by = 2), locals = LocalCapture.CAPTURE_FAILHARD) 24 | private void readPaletteNBT(World world, NBTTagCompound nbt, CallbackInfoReturnable cir, 25 | int ignored0, int ignored1, Chunk ignored2, NBTTagList ignored3, int ingnored4, ExtendedBlockStorage[] ignored5, boolean ignored6, int ignored7, 26 | NBTTagCompound storageNBT, int y, ExtendedBlockStorage extendedBlockStorage) { 27 | int[] palette = storageNBT.hasKey("Palette", 11) ? storageNBT.getIntArray("Palette") : null; 28 | ((INewBlockStateContainer) extendedBlockStorage.getData()).setTemporaryPalette(palette); 29 | } 30 | 31 | /** @reason Write palette to NBT for JustEnoughIDs BlockStateContainers. */ 32 | @Inject(method = "writeChunkToNBT", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/chunk/BlockStateContainer;getDataForNBT([BLnet/minecraft/world/chunk/NibbleArray;)Lnet/minecraft/world/chunk/NibbleArray;", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD) 33 | private void writePaletteNBT(Chunk chunk, World worldIn, NBTTagCompound nbt, CallbackInfo ci, 34 | ExtendedBlockStorage[] ignored0, NBTTagList ignored1, boolean ignored2, ExtendedBlockStorage[] ignored3, int ignored4, int ignored5, 35 | ExtendedBlockStorage extendedBlockStorage, NBTTagCompound storageNBT, byte[] blocks, NibbleArray data, NibbleArray add) { 36 | int[] palette = ((INewBlockStateContainer) extendedBlockStorage.getData()).getTemporaryPalette(); 37 | if (palette != null) storageNBT.setIntArray("Palette", palette); 38 | } 39 | 40 | /** @reason Read int biome array from NBT if it's there. */ 41 | @Inject(method = "readChunkFromNBT", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/NBTTagCompound;hasKey(Ljava/lang/String;I)Z", ordinal = 1), locals = LocalCapture.CAPTURE_FAILHARD) 42 | private void readBiomeArray(World world, NBTTagCompound nbt, CallbackInfoReturnable cir, 43 | int ignored0, int ignored1, 44 | Chunk chunk, 45 | NBTTagList ignored2, int ignored3, ExtendedBlockStorage[] ignored4, boolean ignored5) { 46 | INewChunk newChunk = (INewChunk) chunk; 47 | if (nbt.hasKey("Biomes", 11)) { 48 | newChunk.setIntBiomeArray(nbt.getIntArray("Biomes")); 49 | } else { 50 | // Convert old chunks 51 | int[] intBiomeArray = new int[256]; 52 | int index = 0; 53 | for (byte b : nbt.getByteArray("Biomes")) { 54 | intBiomeArray[index++] = b & 0xFF; 55 | } 56 | newChunk.setIntBiomeArray(intBiomeArray); 57 | } 58 | } 59 | 60 | /** @reason Disable default biome array save logic. */ 61 | @Redirect(method = "writeChunkToNBT", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/NBTTagCompound;setByteArray(Ljava/lang/String;[B)V", ordinal = 6)) 62 | private void defaultWriteBiomeArray(NBTTagCompound nbt, String key, byte[] value) { 63 | if (!key.equals("Biomes")) throw new AssertionError("Ordinal 6 of setByteArray isn't \"Biomes\""); 64 | } 65 | 66 | /** @reason Disable default biome array save logic. */ 67 | @Redirect(method = "writeChunkToNBT", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/chunk/Chunk;getBiomeArray()[B", ordinal = 0)) 68 | private byte[] defaultWriteBiomeArray(Chunk chunk) { 69 | return new byte[0]; 70 | } 71 | 72 | /** @reason Save the correct biome array type */ 73 | @Inject(method = "writeChunkToNBT", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/NBTTagCompound;setByteArray(Ljava/lang/String;[B)V", ordinal = 6)) 74 | private void writeBiomeArray(Chunk chunk, World worldIn, NBTTagCompound nbt, CallbackInfo ci) { 75 | INewChunk newChunk = (INewChunk) chunk; 76 | nbt.setIntArray("Biomes", newChunk.getIntBiomeArray()); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinBlock.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import net.minecraft.block.Block; 4 | import net.minecraft.block.state.IBlockState; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.Overwrite; 7 | import org.spongepowered.asm.mixin.Shadow; 8 | 9 | @Mixin(Block.class) 10 | public abstract class MixinBlock { 11 | @Shadow public static int getIdFromBlock(Block blockIn) { return 0; } 12 | @Shadow public static Block getBlockById(int id) { return null; } 13 | 14 | /** 15 | * @reason Use JustEnoughIDs ID format (id, meta rather than meta, id) for 16 | * blocks with an ID larger than 4096. 17 | **/ 18 | @Overwrite 19 | public static int getStateId(IBlockState state) { 20 | Block block = state.getBlock(); 21 | int id = getIdFromBlock(block); 22 | int meta = block.getMetaFromState(state); 23 | if ((id & 0xfffff000) == 0) { 24 | // Use vanilla 4 bit meta + 12 bit ID 25 | return id + (meta << 12); 26 | } else { 27 | // Use JEID 28 bit ID + 4 bit meta 28 | return (id << 4) + meta; 29 | } 30 | } 31 | 32 | /** 33 | * @reason Use JustEnoughIDs ID format (id, meta rather than meta, id) for blocks with 34 | * an ID larger than 4096 stored in JEID format (state ID is larger than 65536) 35 | **/ 36 | @Overwrite 37 | @SuppressWarnings("deprecation") 38 | public static IBlockState getStateById(int stateID) { 39 | if ((stateID & 0xffff0000) == 0) { 40 | // Use vanilla 4 bit meta + 12 bit ID 41 | int id = stateID & 4095; 42 | int meta = stateID >> 12 & 15; 43 | return getBlockById(id).getStateFromMeta(meta); 44 | } else { 45 | // Use JEID 28 bit ID + 4 bit meta 46 | int meta = stateID & 0xF; 47 | int blockID = stateID >> 4; 48 | return getBlockById(blockID).getStateFromMeta(meta); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinBlockStateContainer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import net.minecraft.block.Block; 4 | import net.minecraft.block.state.IBlockState; 5 | import net.minecraft.util.BitArray; 6 | import net.minecraft.world.chunk.BlockStateContainer; 7 | import net.minecraft.world.chunk.IBlockStatePalette; 8 | import net.minecraft.world.chunk.NibbleArray; 9 | import org.dimdev.jeid.INewBlockStateContainer; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | import org.spongepowered.asm.mixin.injection.Inject; 14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 16 | 17 | import java.util.HashMap; 18 | import java.util.Map; 19 | 20 | @Mixin(BlockStateContainer.class) 21 | public abstract class MixinBlockStateContainer implements INewBlockStateContainer { 22 | @Shadow protected abstract IBlockState get(int index); 23 | @Shadow @SuppressWarnings("unused") protected BitArray storage; 24 | @Shadow @SuppressWarnings("unused") protected IBlockStatePalette palette; 25 | @Shadow protected abstract void set(int index, IBlockState state); 26 | @Shadow @SuppressWarnings("unused") protected abstract void setBits(int bitsIn); 27 | 28 | private int[] temporaryPalette; // index -> state id 29 | 30 | @Override 31 | public int[] getTemporaryPalette() { 32 | return temporaryPalette; 33 | } 34 | 35 | @Override 36 | public void setTemporaryPalette(int[] temporaryPalette) { 37 | this.temporaryPalette = temporaryPalette; 38 | } 39 | 40 | /** 41 | * @reason If this BlockStateContainer should be saved in JustEnoughIDs format, 42 | * store palette IDs rather than block IDs in the container's "Blocks" and 43 | * "Data" arrays. 44 | */ 45 | @SuppressWarnings("deprecation") 46 | @Inject(method = "getDataForNBT", at = @At("HEAD"), cancellable = true) 47 | private void newGetDataForNBT(byte[] blockIds, NibbleArray data, CallbackInfoReturnable cir) { 48 | HashMap stateIDMap = new HashMap<>(); 49 | int nextID = 0; 50 | for (int index = 0; index < 4096; ++index) { 51 | IBlockState state = get(index); 52 | Integer paletteID = stateIDMap.get(state); 53 | if (paletteID == null) { 54 | paletteID = nextID++; 55 | stateIDMap.put(state, paletteID); 56 | } 57 | 58 | int x = index & 15; 59 | int y = index >> 8 & 15; 60 | int z = index >> 4 & 15; 61 | 62 | blockIds[index] = (byte) (paletteID >> 4 & 255); 63 | data.set(x, y, z, paletteID & 15); 64 | } 65 | 66 | temporaryPalette = new int[nextID]; 67 | for (Map.Entry entry : stateIDMap.entrySet()) { 68 | temporaryPalette[entry.getValue()] = Block.BLOCK_STATE_IDS.get(entry.getKey()); 69 | } 70 | 71 | cir.setReturnValue(null); 72 | cir.cancel(); 73 | } 74 | 75 | /** 76 | * @reason If this BlockStateContainer is saved in JustEnoughIDs format, treat 77 | * the "Blocks" and "Data" arrays as palette IDs. 78 | */ 79 | @SuppressWarnings("deprecation") 80 | @Inject(method = "setDataFromNBT", at = @At("HEAD"), cancellable = true) 81 | private void newSetDataFromNBT(byte[] blockIds, NibbleArray data, NibbleArray blockIdExtension, CallbackInfo ci) { 82 | if (temporaryPalette == null) return; // Read containers in in pallette format only if the container has a palette (has a palette) 83 | 84 | for (int index = 0; index < 4096; ++index) { 85 | int x = index & 15; 86 | int y = index >> 8 & 15; 87 | int z = index >> 4 & 15; 88 | int paletteID = (blockIds[index] & 255) << 4 | data.get(x, y, z); 89 | 90 | set(index, Block.BLOCK_STATE_IDS.getByValue(temporaryPalette[paletteID])); 91 | } 92 | 93 | temporaryPalette = null; 94 | ci.cancel(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinChunk.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import net.minecraft.init.Biomes; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraft.world.World; 6 | import net.minecraft.world.biome.Biome; 7 | import net.minecraft.world.biome.BiomeProvider; 8 | import net.minecraft.world.chunk.Chunk; 9 | import org.dimdev.jeid.INewChunk; 10 | import org.dimdev.jeid.JEID; 11 | import org.spongepowered.asm.mixin.Final; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Overwrite; 14 | import org.spongepowered.asm.mixin.Shadow; 15 | 16 | import java.util.Arrays; 17 | 18 | @Mixin(Chunk.class) 19 | public class MixinChunk implements INewChunk { 20 | 21 | 22 | @Shadow @Final private World world; 23 | 24 | private static final byte errorBiomeID = (byte) Biome.REGISTRY.getIDForObject(JEID.errorBiome); 25 | private final int[] intBiomeArray = generateIntBiomeArray(); 26 | 27 | private static int[] generateIntBiomeArray() { 28 | int[] arr = new int[256]; 29 | Arrays.fill(arr, -1); 30 | return arr; 31 | } 32 | 33 | @Override 34 | public int[] getIntBiomeArray() { 35 | return intBiomeArray; 36 | } 37 | 38 | @Override 39 | public void setIntBiomeArray(int[] intBiomeArray) { 40 | System.arraycopy(intBiomeArray, 0, this.intBiomeArray, 0, this.intBiomeArray.length); 41 | } 42 | 43 | /** 44 | * @author Unknown 45 | */ 46 | @Overwrite 47 | public byte[] getBiomeArray() { 48 | byte[] arr = new byte[256]; 49 | Arrays.fill(arr, errorBiomeID); 50 | return arr; 51 | } 52 | 53 | /** 54 | * @author Clienthax 55 | * @reason No way to modify locals in the manner we need currently.. 56 | */ 57 | @Overwrite 58 | public Biome getBiome(BlockPos pos, BiomeProvider provider) 59 | { 60 | int i = pos.getX() & 15; 61 | int j = pos.getZ() & 15; 62 | //JEID START 63 | int k = this.intBiomeArray[j << 4 | i]; 64 | //JEID END 65 | 66 | if (k == 255) 67 | { 68 | // Forge: checking for client ensures that biomes are only generated on integrated server 69 | // in singleplayer. Generating biomes on the client may corrupt the biome ID arrays on 70 | // the server while they are being generated because IntCache can't be thread safe, 71 | // so client and server may end up filling the same array. 72 | // This is not necessary in 1.13 and newer versions. 73 | Biome biome = world.isRemote ? Biomes.PLAINS : provider.getBiome(pos, Biomes.PLAINS); 74 | k = Biome.getIdForBiome(biome); 75 | //JEID START 76 | this.intBiomeArray[j << 4 | i] = k; 77 | //JEID END 78 | } 79 | 80 | Biome biome1 = Biome.getBiome(k); 81 | return biome1 == null ? Biomes.PLAINS : biome1; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinChunkPrimer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import net.minecraft.block.Block; 4 | import net.minecraft.block.state.IBlockState; 5 | import net.minecraft.world.chunk.ChunkPrimer; 6 | import org.spongepowered.asm.mixin.Final; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Overwrite; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Inject; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 13 | 14 | @Mixin(ChunkPrimer.class) 15 | @SuppressWarnings("deprecation") 16 | public abstract class MixinChunkPrimer { 17 | @Shadow private static int getBlockIndex(int x, int y, int z) { return 0; } 18 | @Shadow @Final private static IBlockState DEFAULT_STATE; 19 | private int[] intData = new int[65536]; 20 | 21 | @Overwrite 22 | public IBlockState getBlockState(int x, int y, int z) { 23 | IBlockState state = Block.BLOCK_STATE_IDS.getByValue(intData[getBlockIndex(x, y, z)]); 24 | return state == null ? DEFAULT_STATE : state; 25 | } 26 | 27 | @Inject(method = "setBlockState", at = @At(value = "FIELD", target = "Lnet/minecraft/world/chunk/ChunkPrimer;data:[C"), cancellable = true) 28 | private void setIntBlockState(int x, int y, int z, IBlockState state, CallbackInfo ci) { 29 | intData[getBlockIndex(x, y, z)] = Block.BLOCK_STATE_IDS.get(state); 30 | ci.cancel(); 31 | } 32 | 33 | @Overwrite 34 | public int findGroundBlockIdx(int x, int z) { 35 | int xz = (x << 12 | z << 8) + 256 - 1; 36 | for (int y = 255; y >= 0; --y) { 37 | IBlockState iblockstate = Block.BLOCK_STATE_IDS.getByValue(intData[xz + y]); 38 | if (iblockstate != null && iblockstate != DEFAULT_STATE) return y; 39 | } 40 | 41 | return 0; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinChunkProviderServer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import net.minecraft.world.WorldServer; 4 | import net.minecraft.world.biome.Biome; 5 | import net.minecraft.world.chunk.Chunk; 6 | import net.minecraft.world.gen.ChunkProviderServer; 7 | import org.dimdev.jeid.INewChunk; 8 | import org.spongepowered.asm.mixin.Final; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 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 org.spongepowered.asm.mixin.injection.callback.LocalCapture; 15 | 16 | @Mixin(ChunkProviderServer.class) 17 | public class MixinChunkProviderServer { 18 | @Shadow @Final public WorldServer world; 19 | private Biome[] reusableBiomeList = new Biome[256]; 20 | 21 | /** @reason Return an empty biome byte array if the chunk is using an int biome array. **/ 22 | @Inject(method = "provideChunk", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/gen/IChunkGenerator;generateChunk(II)Lnet/minecraft/world/chunk/Chunk;"), locals = LocalCapture.CAPTURE_FAILHARD) 23 | private void initializeBiomeArray(int x, int z, CallbackInfoReturnable cir, Chunk chunk) { 24 | Biome[] biomes = world.getBiomeProvider().getBiomes(reusableBiomeList, x * 16, z * 16, 16, 16); 25 | 26 | INewChunk newChunk = (INewChunk) chunk; 27 | int[] intBiomeArray = newChunk.getIntBiomeArray(); 28 | for (int i = 0; i < intBiomeArray.length; ++i) { 29 | intBiomeArray[i] = Biome.getIdForBiome(biomes[i]); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinEnchantmentHelper.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import com.google.common.collect.Maps; 4 | import net.minecraft.enchantment.Enchantment; 5 | import net.minecraft.enchantment.EnchantmentData; 6 | import net.minecraft.enchantment.EnchantmentHelper; 7 | import net.minecraft.init.Items; 8 | import net.minecraft.item.ItemEnchantedBook; 9 | import net.minecraft.item.ItemStack; 10 | import net.minecraft.nbt.NBTTagCompound; 11 | import net.minecraft.nbt.NBTTagList; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Overwrite; 14 | 15 | import java.util.Map; 16 | 17 | @Mixin(EnchantmentHelper.class) 18 | public class MixinEnchantmentHelper { 19 | 20 | /** @reason Mojang really likes modifying their original type into something else **/ 21 | @Overwrite 22 | public static int getEnchantmentLevel(Enchantment enchID, ItemStack stack) 23 | { 24 | if (stack.isEmpty()) 25 | { 26 | return 0; 27 | } 28 | else 29 | { 30 | NBTTagList nbttaglist = stack.getEnchantmentTagList(); 31 | 32 | for (int i = 0; i < nbttaglist.tagCount(); ++i) 33 | { 34 | NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i); 35 | Enchantment enchantment = Enchantment.getEnchantmentByID(nbttagcompound.getInteger("id")); 36 | 37 | if (enchantment == enchID) 38 | { 39 | return nbttagcompound.getShort("lvl"); 40 | } 41 | } 42 | 43 | return 0; 44 | } 45 | } 46 | 47 | /** @reason Mojang really likes modifying their original type into something else **/ 48 | @Overwrite 49 | public static Map getEnchantments(ItemStack stack) 50 | { 51 | Map map = Maps.newLinkedHashMap(); 52 | NBTTagList nbttaglist = stack.getItem() == Items.ENCHANTED_BOOK ? ItemEnchantedBook.getEnchantments(stack) : stack.getEnchantmentTagList(); 53 | 54 | for (int i = 0; i < nbttaglist.tagCount(); ++i) 55 | { 56 | NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i); 57 | Enchantment enchantment = Enchantment.getEnchantmentByID(nbttagcompound.getInteger("id")); 58 | map.put(enchantment, Integer.valueOf(nbttagcompound.getShort("lvl"))); 59 | } 60 | 61 | return map; 62 | } 63 | 64 | @Overwrite 65 | public static void setEnchantments(Map enchMap, ItemStack stack) 66 | { 67 | NBTTagList nbttaglist = new NBTTagList(); 68 | 69 | for (Map.Entry entry : enchMap.entrySet()) 70 | { 71 | Enchantment enchantment = entry.getKey(); 72 | 73 | if (enchantment != null) 74 | { 75 | NBTTagCompound nbttagcompound = new NBTTagCompound(); 76 | nbttagcompound.setInteger("id", Enchantment.getEnchantmentID(enchantment)); 77 | nbttagcompound.setShort("lvl", entry.getValue().shortValue()); 78 | nbttaglist.appendTag(nbttagcompound); 79 | 80 | if (stack.getItem() == Items.ENCHANTED_BOOK) { ItemEnchantedBook.addEnchantment(stack, new EnchantmentData(enchantment, entry.getValue().shortValue())); } 81 | } 82 | } 83 | 84 | if (nbttaglist.isEmpty()) 85 | { 86 | if (stack.hasTagCompound()) 87 | { 88 | stack.getTagCompound().removeTag("ench"); 89 | } 90 | } 91 | else if (stack.getItem() != Items.ENCHANTED_BOOK) 92 | { 93 | stack.setTagInfo("ench", nbttaglist); 94 | } 95 | } 96 | 97 | @Overwrite 98 | private static void applyEnchantmentModifier(EnchantmentHelper.IModifier modifier, ItemStack stack) 99 | { 100 | if (!stack.isEmpty()) 101 | { 102 | NBTTagList nbttaglist = stack.getEnchantmentTagList(); 103 | 104 | for (int i = 0; i < nbttaglist.tagCount(); ++i) 105 | { 106 | if (Enchantment.getEnchantmentByID(nbttaglist.getCompoundTagAt(i).getInteger("id")) != null) 107 | { 108 | modifier.calculateModifier(Enchantment.getEnchantmentByID(nbttaglist.getCompoundTagAt(i).getInteger("id")), nbttaglist.getCompoundTagAt(i).getShort("lvl")); 109 | } 110 | } 111 | } 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinGameData.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import net.minecraftforge.registries.GameData; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.injection.Constant; 6 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 7 | 8 | /** 9 | * Removes ID limits from forge registries. These are @ModifyConstants since javac 10 | * automatically inlines all static final fields that are constant expressions 11 | * (https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28) 12 | */ 13 | @Mixin(value = GameData.class, priority = 500) 14 | public abstract class MixinGameData { 15 | /** @reason Removes the block ID limit. */ 16 | @ModifyConstant(method = "init", constant = @Constant(intValue = 4095, ordinal = 0), remap = false) 17 | private static int getBlockIDLimit(int value) { 18 | return Integer.MAX_VALUE - 1; 19 | } 20 | 21 | /** @reason Removes the item ID limit. */ 22 | @ModifyConstant(method = "init", constant = @Constant(intValue = 31999, ordinal = 0), remap = false) 23 | private static int getItemIDLimit(int value) { 24 | return Integer.MAX_VALUE - 1; 25 | } 26 | 27 | /** @reason Removes the potion ID limit. */ 28 | @ModifyConstant(method = "init", constant = @Constant(intValue = 255, ordinal = 0), remap = false) 29 | private static int getPotionIDLimit(int value) { 30 | return Integer.MAX_VALUE - 1; 31 | } 32 | 33 | /** @reason Removes the biome ID limit. */ 34 | @ModifyConstant(method = "init", constant = @Constant(intValue = 255, ordinal = 1), remap = false) 35 | private static int getBiomeIDLimit(int value) { return Integer.MAX_VALUE - 1; } 36 | 37 | /** @reason Removes the enchantment ID limit. */ 38 | @ModifyConstant(method = "init", constant = @Constant(intValue = Short.MAX_VALUE - 1, ordinal = 0), remap = false) 39 | private static int getEnchantmentIDLimit(int value) { return Integer.MAX_VALUE - 1; } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinGenLayerVoronoiZoom.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import net.minecraft.world.gen.layer.GenLayerVoronoiZoom; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.injection.Constant; 6 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 7 | 8 | @Mixin(GenLayerVoronoiZoom.class) 9 | public abstract class MixinGenLayerVoronoiZoom { 10 | @ModifyConstant(method = "getInts", constant = @Constant(intValue = 255)) 11 | private int getBitMask(int oldValue) { 12 | return 0xFFFFFFFF; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinItemEnchantedBook.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import net.minecraft.client.util.ITooltipFlag; 4 | import net.minecraft.enchantment.Enchantment; 5 | import net.minecraft.enchantment.EnchantmentData; 6 | import net.minecraft.item.Item; 7 | import net.minecraft.item.ItemEnchantedBook; 8 | import net.minecraft.item.ItemStack; 9 | import net.minecraft.nbt.NBTTagCompound; 10 | import net.minecraft.nbt.NBTTagList; 11 | import net.minecraft.world.World; 12 | import net.minecraftforge.fml.relauncher.Side; 13 | import net.minecraftforge.fml.relauncher.SideOnly; 14 | import org.spongepowered.asm.mixin.Mixin; 15 | import org.spongepowered.asm.mixin.Overwrite; 16 | import org.spongepowered.asm.mixin.Shadow; 17 | 18 | import javax.annotation.Nullable; 19 | import java.util.List; 20 | 21 | @Mixin(ItemEnchantedBook.class) 22 | public class MixinItemEnchantedBook extends Item { 23 | 24 | @Shadow public static NBTTagList getEnchantments(ItemStack p_92110_0_) { NBTTagCompound nbttagcompound = p_92110_0_.getTagCompound(); 25 | return nbttagcompound != null ? nbttagcompound.getTagList("StoredEnchantments", 10) : new NBTTagList(); } 26 | 27 | @Overwrite 28 | @SideOnly(Side.CLIENT) 29 | public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) 30 | { 31 | super.addInformation(stack, worldIn, tooltip, flagIn); 32 | NBTTagList nbttaglist = getEnchantments(stack); 33 | 34 | for (int i = 0; i < nbttaglist.tagCount(); ++i) 35 | { 36 | NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i); 37 | Enchantment enchantment = Enchantment.getEnchantmentByID(nbttagcompound.getInteger("id")); 38 | 39 | if (enchantment != null) 40 | { 41 | tooltip.add(enchantment.getTranslatedName(nbttagcompound.getShort("lvl"))); 42 | } 43 | } 44 | } 45 | 46 | @Overwrite 47 | public static void addEnchantment(ItemStack p_92115_0_, EnchantmentData stack) 48 | { 49 | NBTTagList nbttaglist = getEnchantments(p_92115_0_); 50 | boolean flag = true; 51 | 52 | for (int i = 0; i < nbttaglist.tagCount(); ++i) 53 | { 54 | NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i); 55 | 56 | if (Enchantment.getEnchantmentByID(nbttagcompound.getInteger("id")) == stack.enchantment) 57 | { 58 | if (nbttagcompound.getShort("lvl") < stack.enchantmentLevel) 59 | { 60 | nbttagcompound.setShort("lvl", (short)stack.enchantmentLevel); 61 | } 62 | 63 | flag = false; 64 | break; 65 | } 66 | } 67 | 68 | if (flag) 69 | { 70 | NBTTagCompound nbttagcompound1 = new NBTTagCompound(); 71 | nbttagcompound1.setInteger("id", Enchantment.getEnchantmentID(stack.enchantment)); 72 | nbttagcompound1.setShort("lvl", (short)stack.enchantmentLevel); 73 | nbttaglist.appendTag(nbttagcompound1); 74 | } 75 | 76 | if (!p_92115_0_.hasTagCompound()) 77 | { 78 | p_92115_0_.setTagCompound(new NBTTagCompound()); 79 | } 80 | 81 | p_92115_0_.getTagCompound().setTag("StoredEnchantments", nbttaglist); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinPacketBuffer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import net.minecraft.item.Item; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.nbt.NBTTagCompound; 7 | import net.minecraft.network.PacketBuffer; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Inject; 12 | import org.spongepowered.asm.mixin.injection.Redirect; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 14 | 15 | import javax.annotation.Nullable; 16 | import java.io.IOException; 17 | 18 | @Mixin(PacketBuffer.class) 19 | public abstract class MixinPacketBuffer { 20 | @Shadow public abstract byte readByte(); 21 | 22 | @Shadow public abstract short readShort(); 23 | 24 | @Shadow public abstract int readVarInt(); 25 | 26 | @Shadow @Nullable public abstract NBTTagCompound readCompoundTag() throws IOException; 27 | 28 | @Shadow public abstract PacketBuffer writeVarInt(int input); 29 | 30 | @Redirect(method = "writeItemStack", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/PacketBuffer;writeShort(I)Lio/netty/buffer/ByteBuf;", ordinal = 0)) 31 | private ByteBuf writeIntItemId(PacketBuffer packetBuffer, int p_writeShort_1_) { 32 | return this.writeVarInt(p_writeShort_1_); 33 | } 34 | 35 | @Redirect(method = "writeItemStack", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/PacketBuffer;writeShort(I)Lio/netty/buffer/ByteBuf;", ordinal = 1)) 36 | private ByteBuf writeIntItemId1(PacketBuffer packetBuffer, int p_writeShort_1_) { 37 | return this.writeVarInt(p_writeShort_1_); 38 | } 39 | 40 | 41 | @Inject(method = "readItemStack", at = @At(value = "HEAD"), cancellable = true) 42 | private void readIntItemId(CallbackInfoReturnable cir) throws IOException { 43 | int i = this.readVarInt(); 44 | 45 | if (i < 0) { 46 | cir.setReturnValue(ItemStack.EMPTY); 47 | } else { 48 | int j = this.readByte(); 49 | int k = this.readShort(); 50 | ItemStack itemstack = new ItemStack(Item.getItemById(i), j, k); 51 | itemstack.getItem().readNBTShareTag(itemstack, this.readCompoundTag()); 52 | cir.setReturnValue(itemstack); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinSPacketChunkData.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import net.minecraft.network.PacketBuffer; 4 | import net.minecraft.network.play.server.SPacketChunkData; 5 | import net.minecraft.world.chunk.Chunk; 6 | import org.dimdev.jeid.INewChunk; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.Redirect; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 13 | 14 | @Mixin(SPacketChunkData.class) 15 | public abstract class MixinSPacketChunkData { 16 | @Shadow public abstract boolean isFullChunk(); 17 | 18 | /** @reason Write the biome int array. **/ 19 | @Inject(method = "extractChunkData", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/play/server/SPacketChunkData;isFullChunk()Z", ordinal = 1)) 20 | public void writeBiomeArray(PacketBuffer buf, Chunk chunk, boolean writeSkylight, int changedSectionFilter, CallbackInfoReturnable cir) { 21 | if (isFullChunk()) { 22 | buf.writeVarIntArray(((INewChunk) chunk).getIntBiomeArray()); 23 | } 24 | } 25 | 26 | /** @reason Disable writing biome byte array. **/ 27 | @Redirect(method = "extractChunkData", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/play/server/SPacketChunkData;isFullChunk()Z", ordinal = 1)) 28 | public boolean getIsFullChunk(SPacketChunkData packet) { 29 | return false; 30 | } 31 | 32 | /** @reason Disable adding biome byte array size. **/ 33 | @Redirect(method = "calculateChunkSize", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/play/server/SPacketChunkData;isFullChunk()Z", ordinal = 1)) 34 | public boolean getIsFullChunk1(SPacketChunkData packet) { 35 | return false; 36 | } 37 | 38 | @Inject(method = "calculateChunkSize", at = @At(value = "RETURN"), cancellable = true) 39 | public void onReturn(Chunk chunkIn, boolean p_189556_2_, int p_189556_3_, CallbackInfoReturnable ci) { 40 | if (this.isFullChunk()) { 41 | int size = ci.getReturnValue(); 42 | 43 | // Now, we add on the actual length of the VarIntArray we're going to be writing in extractChunkData 44 | size += this.getVarIntArraySize(((INewChunk) chunkIn).getIntBiomeArray()); 45 | ci.setReturnValue(size); 46 | } 47 | } 48 | 49 | private int getVarIntArraySize(int[] array) { 50 | int size = PacketBuffer.getVarIntSize(array.length); 51 | for (int i: array) { 52 | size += PacketBuffer.getVarIntSize(i); 53 | } 54 | return size; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinStatList.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import com.google.common.collect.Sets; 4 | import net.minecraft.block.Block; 5 | import net.minecraft.init.Items; 6 | import net.minecraft.item.Item; 7 | import net.minecraft.item.ItemBlock; 8 | import net.minecraft.item.ItemStack; 9 | import net.minecraft.item.crafting.CraftingManager; 10 | import net.minecraft.item.crafting.FurnaceRecipes; 11 | import net.minecraft.item.crafting.IRecipe; 12 | import net.minecraft.stats.StatBase; 13 | import net.minecraft.stats.StatCrafting; 14 | import net.minecraft.stats.StatList; 15 | import net.minecraft.util.ResourceLocation; 16 | import net.minecraft.util.text.TextComponentTranslation; 17 | import org.spongepowered.asm.mixin.Final; 18 | import org.spongepowered.asm.mixin.Mixin; 19 | import org.spongepowered.asm.mixin.Overwrite; 20 | import org.spongepowered.asm.mixin.Shadow; 21 | 22 | import javax.annotation.Nullable; 23 | import java.util.*; 24 | 25 | /** Rewrite most of the class to support an unlimited number of IDs (map rather than array). **/ 26 | @Mixin(value = StatList.class, priority = 500) 27 | public final class MixinStatList { 28 | @Shadow @Final protected static Map ID_TO_STAT_MAP; 29 | @Shadow @Final public static List BASIC_STATS; 30 | @Shadow @Final public static List USE_ITEM_STATS; 31 | @Shadow @Final public static List MINE_BLOCK_STATS; 32 | 33 | @Shadow @Final public static List ALL_STATS; 34 | private static final Map BLOCK_STAT_MAP = new HashMap<>(); 35 | private static final Map CRAFTS_STATS_MAP = new HashMap<>(); 36 | private static final Map OBJECT_USE_STATS_MAP = new HashMap<>(); 37 | private static final Map OBJECT_BREAK_STATS_MAP = new HashMap<>(); 38 | private static final Map OBJECTS_PICKED_UP_STATS_MAP = new HashMap<>(); 39 | private static final Map OBJECTS_DROPPED_STATS_MAP = new HashMap<>(); 40 | 41 | @Overwrite @Nullable public static StatBase getBlockStats(Block block) { return BLOCK_STAT_MAP.get(block); } 42 | @Overwrite @Nullable public static StatBase getCraftStats(Item item) { return CRAFTS_STATS_MAP.get(item); } 43 | @Overwrite @Nullable public static StatBase getObjectUseStats(Item item) { return OBJECT_USE_STATS_MAP.get(item); } 44 | @Overwrite @Nullable public static StatBase getObjectBreakStats(Item item) { return OBJECT_BREAK_STATS_MAP.get(item); } 45 | @Overwrite @Nullable public static StatBase getObjectsPickedUpStats(Item item) { return OBJECTS_PICKED_UP_STATS_MAP.get(item); } 46 | @Overwrite @Nullable public static StatBase getDroppedObjectStats(Item item) { return OBJECTS_DROPPED_STATS_MAP.get(item); } 47 | 48 | @Overwrite 49 | public static void init() { 50 | initMiningStats(); 51 | initStats(); 52 | initItemDepleteStats(); 53 | initCraftableStats(); 54 | initPickedUpAndDroppedStats(); 55 | } 56 | 57 | @Overwrite 58 | private static void initMiningStats() { 59 | for (Block block : Block.REGISTRY) { 60 | Item item = Item.getItemFromBlock(block); 61 | 62 | if (block.getEnableStats() && item != Items.AIR && getItemName(item) != null) { 63 | StatCrafting stat = new StatCrafting( 64 | "stat.mineBlock.", 65 | getItemName(item), new TextComponentTranslation("stat.mineBlock", new ItemStack(block).getTextComponent()), 66 | item); 67 | 68 | MINE_BLOCK_STATS.add(stat); 69 | BLOCK_STAT_MAP.put(block, stat); 70 | stat.registerStat(); 71 | } 72 | } 73 | } 74 | 75 | @Overwrite 76 | private static void initStats() { 77 | for (Item item : Item.REGISTRY) { 78 | if (item != null && getItemName(item) != null) { 79 | StatCrafting stat = new StatCrafting("stat.useItem.", 80 | getItemName(item), 81 | new TextComponentTranslation("stat.useItem", new ItemStack(item).getTextComponent()), 82 | item); 83 | 84 | OBJECT_USE_STATS_MAP.put(item, stat); 85 | if (!(item instanceof ItemBlock)) USE_ITEM_STATS.add(stat); 86 | stat.registerStat(); 87 | } 88 | } 89 | } 90 | 91 | @Overwrite 92 | private static void initCraftableStats() { 93 | Set craftableItems = Sets.newHashSet(); 94 | 95 | for (IRecipe recipe : CraftingManager.REGISTRY) { 96 | ItemStack output = recipe.getRecipeOutput(); 97 | if (!output.isEmpty()) craftableItems.add(recipe.getRecipeOutput().getItem()); 98 | } 99 | 100 | for (ItemStack furnaceRecipeOutputs : FurnaceRecipes.instance().getSmeltingList().values()) { 101 | craftableItems.add(furnaceRecipeOutputs.getItem()); 102 | } 103 | 104 | for (Item item : craftableItems) { 105 | if (item != null && getItemName(item) != null) { 106 | StatCrafting stat = new StatCrafting( 107 | "stat.craftItem.", 108 | getItemName(item), 109 | new TextComponentTranslation("stat.craftItem", new ItemStack(item).getTextComponent()), 110 | item); 111 | 112 | CRAFTS_STATS_MAP.put(item, stat); 113 | stat.registerStat(); 114 | } 115 | } 116 | } 117 | 118 | @Overwrite 119 | private static void initItemDepleteStats() { 120 | for (Item item : Item.REGISTRY) { 121 | if (item != null && getItemName(item) != null && item.isDamageable()) { 122 | StatCrafting stat = new StatCrafting( 123 | "stat.breakItem.", 124 | getItemName(item), 125 | new TextComponentTranslation("stat.breakItem", new ItemStack(item).getTextComponent()), 126 | item); 127 | 128 | OBJECT_BREAK_STATS_MAP.put(item, stat); 129 | stat.registerStat(); 130 | } 131 | } 132 | } 133 | 134 | private static void initPickedUpAndDroppedStats() { 135 | for (Item item : Item.REGISTRY) 136 | if (item != null && getItemName(item) != null) { 137 | StatCrafting pickupStat = new StatCrafting( 138 | "stat.pickup.", 139 | getItemName(item), 140 | new TextComponentTranslation("stat.pickup", new ItemStack(item).getTextComponent()), 141 | item); 142 | 143 | StatCrafting dropStat = new StatCrafting( 144 | "stat.drop.", 145 | getItemName(item), 146 | new TextComponentTranslation("stat.drop", new ItemStack(item).getTextComponent()), 147 | item); 148 | 149 | OBJECTS_PICKED_UP_STATS_MAP.put(item, pickupStat); 150 | OBJECTS_DROPPED_STATS_MAP.put(item, dropStat); 151 | pickupStat.registerStat(); 152 | dropStat.registerStat(); 153 | } 154 | } 155 | 156 | private static String getItemName(Item itemIn) { 157 | ResourceLocation resourcelocation = Item.REGISTRY.getNameForObject(itemIn); 158 | return resourcelocation != null ? resourcelocation.toString().replace(':', '.') : null; 159 | } 160 | 161 | @Overwrite 162 | @Deprecated 163 | public static void reinit() { // Forge 164 | ID_TO_STAT_MAP.clear(); 165 | BASIC_STATS.clear(); 166 | USE_ITEM_STATS.clear(); 167 | MINE_BLOCK_STATS.clear(); 168 | 169 | HashSet knownStats = new HashSet<>(); 170 | knownStats.addAll(BLOCK_STAT_MAP.values()); 171 | knownStats.addAll(CRAFTS_STATS_MAP.values()); 172 | knownStats.addAll(OBJECT_USE_STATS_MAP.values()); 173 | knownStats.addAll(OBJECT_BREAK_STATS_MAP.values()); 174 | knownStats.addAll(OBJECTS_PICKED_UP_STATS_MAP.values()); 175 | knownStats.addAll(OBJECTS_DROPPED_STATS_MAP.values()); 176 | 177 | List unknownStats = new ArrayList<>(); 178 | for (StatBase stat : ALL_STATS) { 179 | if (!knownStats.contains(stat)) { 180 | unknownStats.add(stat); 181 | } 182 | } 183 | 184 | BLOCK_STAT_MAP.clear(); 185 | CRAFTS_STATS_MAP.clear(); 186 | OBJECT_USE_STATS_MAP.clear(); 187 | OBJECT_BREAK_STATS_MAP.clear(); 188 | OBJECTS_PICKED_UP_STATS_MAP.clear(); 189 | OBJECTS_DROPPED_STATS_MAP.clear(); 190 | ALL_STATS.clear(); 191 | 192 | for (StatBase unknownStat : unknownStats) unknownStat.registerStat(); 193 | 194 | init(); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/MixinWorldInfo.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core; 2 | 3 | import net.minecraft.world.storage.WorldInfo; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.injection.Constant; 6 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 7 | 8 | @Mixin(WorldInfo.class) 9 | public class MixinWorldInfo { 10 | @ModifyConstant(method = "updateTagCompound", constant = @Constant(stringValue = "1.12.2", ordinal = 0)) 11 | private String versionName(String currentValue) { 12 | return "1.13-JEID"; 13 | } 14 | 15 | @ModifyConstant(method = "updateTagCompound", constant = @Constant(intValue = 1343, ordinal = 0)) 16 | private int versionId(int currentValue) { 17 | return Integer.MAX_VALUE / 2; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/client/MixinChunk.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core.client; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import net.minecraft.network.PacketBuffer; 5 | import net.minecraft.world.chunk.Chunk; 6 | import org.dimdev.jeid.INewChunk; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Redirect; 10 | 11 | @Mixin(Chunk.class) 12 | public abstract class MixinChunk implements INewChunk { 13 | @Redirect(method = "read", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/PacketBuffer;readBytes([B)Lio/netty/buffer/ByteBuf;", ordinal = 2)) 14 | private ByteBuf readBiomeByteArray(PacketBuffer buf, byte[] dst) { 15 | setIntBiomeArray(buf.readVarIntArray()); 16 | return buf; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/client/MixinRenderGlobal.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core.client; 2 | 3 | import net.minecraft.block.Block; 4 | import net.minecraft.block.SoundType; 5 | import net.minecraft.block.material.Material; 6 | import net.minecraft.block.state.IBlockState; 7 | import net.minecraft.client.Minecraft; 8 | import net.minecraft.client.multiplayer.WorldClient; 9 | import net.minecraft.client.renderer.RenderGlobal; 10 | import net.minecraft.entity.player.EntityPlayer; 11 | import net.minecraft.util.SoundCategory; 12 | import net.minecraft.util.math.BlockPos; 13 | import org.spongepowered.asm.mixin.Final; 14 | import org.spongepowered.asm.mixin.Mixin; 15 | import org.spongepowered.asm.mixin.Shadow; 16 | import org.spongepowered.asm.mixin.injection.At; 17 | import org.spongepowered.asm.mixin.injection.Inject; 18 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 19 | 20 | @Mixin(RenderGlobal.class) 21 | public class MixinRenderGlobal { 22 | @Shadow @Final private Minecraft mc; 23 | @Shadow private WorldClient world; 24 | 25 | @Inject(method = "playEvent", at = @At("HEAD"), cancellable = true) 26 | private void onPlayEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data, CallbackInfo ci) { 27 | if (type == 2001) { 28 | IBlockState state = Block.getStateById(data); 29 | if (state.getMaterial() != Material.AIR) { 30 | SoundType soundtype = state.getBlock().getSoundType(Block.getStateById(data), world, blockPosIn, null); 31 | world.playSound(blockPosIn, soundtype.getBreakSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F, false); 32 | } 33 | mc.effectRenderer.addBlockDestroyEffects(blockPosIn, state); 34 | 35 | ci.cancel(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/core/client/MixinWorldSummary.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.core.client; 2 | 3 | import net.minecraft.world.storage.WorldSummary; 4 | import org.spongepowered.asm.mixin.Final; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.Overwrite; 7 | import org.spongepowered.asm.mixin.Shadow; 8 | 9 | @Mixin(WorldSummary.class) 10 | public class MixinWorldSummary { 11 | @Shadow @Final private int versionId; 12 | 13 | @Overwrite 14 | public boolean askToOpenWorld() { 15 | return versionId > 1343 && versionId != Integer.MAX_VALUE / 2; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/init/JEIDMixinLoader.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.init; 2 | 3 | import net.minecraftforge.fml.common.Loader; 4 | import net.minecraftforge.fml.common.ModClassLoader; 5 | import net.minecraftforge.fml.common.ModContainer; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.MixinEnvironment; 8 | import org.spongepowered.asm.mixin.Mixins; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Inject; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 13 | import org.spongepowered.asm.mixin.transformer.ext.Extensions; 14 | 15 | import java.lang.reflect.Field; 16 | import java.lang.reflect.Method; 17 | import java.net.MalformedURLException; 18 | import java.util.List; 19 | 20 | @Mixin(Loader.class) 21 | public class JEIDMixinLoader { 22 | @Shadow 23 | private List mods; 24 | @Shadow private ModClassLoader modClassLoader; 25 | 26 | /** 27 | * @reason Load all mods now and load mod support mixin configs. This can't be done later 28 | * since constructing mods loads classes from them. 29 | */ 30 | @Inject(method = "loadMods", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/common/LoadController;transition(Lnet/minecraftforge/fml/common/LoaderState;Z)V", ordinal = 1), remap = false) 31 | private void beforeConstructingMods(List nonMod, CallbackInfo ci) { 32 | // Add all mods to class loader 33 | for (ModContainer mod : mods) { 34 | try { 35 | modClassLoader.addFile(mod.getSource()); 36 | } catch (MalformedURLException e) { 37 | throw new RuntimeException(e); 38 | } 39 | } 40 | 41 | // Add and reload mixin configs 42 | Mixins.addConfiguration("mixins.jeid.modsupport.json"); 43 | Mixins.addConfiguration("mixins.jeid.twilightforest.json"); 44 | 45 | try { 46 | // This will very likely break on the next major mixin release. 47 | Class proxyClass = Class.forName("org.spongepowered.asm.mixin.transformer.Proxy"); 48 | Field transformerField = proxyClass.getDeclaredField("transformer"); 49 | transformerField.setAccessible(true); 50 | Object transformer = transformerField.get(null); 51 | 52 | Class mixinTransformerClass = Class.forName("org.spongepowered.asm.mixin.transformer.MixinTransformer"); 53 | Field processorField = mixinTransformerClass.getDeclaredField("processor"); 54 | processorField.setAccessible(true); 55 | Object processor = processorField.get(transformer); 56 | 57 | Class mixinProcessorClass = Class.forName("org.spongepowered.asm.mixin.transformer.MixinProcessor"); 58 | 59 | Field extensionsField = mixinProcessorClass.getDeclaredField("extensions"); 60 | extensionsField.setAccessible(true); 61 | Object extensions = extensionsField.get(processor); 62 | 63 | Method selectConfigsMethod = mixinProcessorClass.getDeclaredMethod("selectConfigs", MixinEnvironment.class); 64 | selectConfigsMethod.setAccessible(true); 65 | selectConfigsMethod.invoke(processor, MixinEnvironment.getCurrentEnvironment()); 66 | 67 | // Mixin 0.8.4+ 68 | try { 69 | Method prepareConfigs = mixinProcessorClass.getDeclaredMethod("prepareConfigs", MixinEnvironment.class, Extensions.class); 70 | prepareConfigs.setAccessible(true); 71 | prepareConfigs.invoke(processor, MixinEnvironment.getCurrentEnvironment(), extensions); 72 | return; 73 | } catch (NoSuchMethodException ex) { 74 | // no-op 75 | } 76 | 77 | // Mixin 0.8+ 78 | try { 79 | Method prepareConfigs = mixinProcessorClass.getDeclaredMethod("prepareConfigs", MixinEnvironment.class); 80 | prepareConfigs.setAccessible(true); 81 | prepareConfigs.invoke(processor, MixinEnvironment.getCurrentEnvironment()); 82 | return; 83 | } catch (NoSuchMethodException ex) { 84 | // no-op 85 | } 86 | 87 | throw new UnsupportedOperationException("Unsupported Mixin"); 88 | } catch (Exception ex) { 89 | throw new RuntimeException(ex); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/abyssalcraft/MixinBiomeUtil.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.abyssalcraft; 2 | 3 | import com.shinoow.abyssalcraft.common.network.PacketDispatcher; 4 | import com.shinoow.abyssalcraft.common.network.client.CleansingRitualMessage; 5 | import com.shinoow.abyssalcraft.common.util.BiomeUtil; 6 | import net.minecraft.util.math.BlockPos; 7 | import net.minecraft.world.World; 8 | import net.minecraft.world.chunk.Chunk; 9 | import org.dimdev.jeid.INewChunk; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Overwrite; 12 | import org.spongepowered.asm.mixin.Pseudo; 13 | 14 | @Pseudo 15 | @Mixin(BiomeUtil.class) 16 | public class MixinBiomeUtil { 17 | @Overwrite(remap = false) 18 | public static void updateBiome(World worldIn, BlockPos pos, int b, boolean batched) { 19 | Chunk c = worldIn.getChunk(pos); 20 | ((INewChunk) c).getIntBiomeArray()[(pos.getZ() & 0xF) << 4 | pos.getX() & 0xF] = b; 21 | c.setModified(true); 22 | if(!worldIn.isRemote) { 23 | PacketDispatcher.sendToDimension(new CleansingRitualMessage(pos.getX(), pos.getZ(), b, batched), worldIn.provider.getDimension()); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/advancedrocketry/MixinBiomeHandler.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.advancedrocketry; 2 | 3 | import net.minecraft.util.math.BlockPos; 4 | import net.minecraft.world.World; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.chunk.Chunk; 7 | import org.dimdev.jeid.INewChunk; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Overwrite; 10 | import org.spongepowered.asm.mixin.Pseudo; 11 | import zmaster587.advancedRocketry.network.PacketBiomeIDChange; 12 | import zmaster587.advancedRocketry.util.BiomeHandler; 13 | import zmaster587.libVulpes.network.PacketHandler; 14 | import zmaster587.libVulpes.util.HashedBlockPosition; 15 | 16 | @Pseudo 17 | @Mixin(BiomeHandler.class) 18 | public class MixinBiomeHandler { 19 | /** 20 | * @author sk2048 21 | */ 22 | @Overwrite 23 | public static void changeBiome(World world, int biomeId, BlockPos pos) { 24 | Chunk chunk = world.getChunk(pos); 25 | 26 | Biome biome = world.getBiome(pos); 27 | Biome biomeTo = Biome.getBiome(biomeId); 28 | 29 | if (biome == biomeTo) 30 | return; 31 | 32 | if (biome.topBlock != biomeTo.topBlock) { 33 | BlockPos yy = world.getHeight(pos); 34 | 35 | for (; !world.getBlockState(yy).isOpaqueCube() || yy.getY() < 0; yy = yy.down()) ; 36 | 37 | if (world.getBlockState(yy) == biome.topBlock) 38 | world.setBlockState(yy, biomeTo.topBlock); 39 | } 40 | 41 | ((INewChunk) chunk).getIntBiomeArray()[(pos.getZ() & 0xF) << 4 | pos.getX() & 0xF] = biomeId; 42 | chunk.markDirty(); 43 | 44 | PacketHandler.sendToNearby(new PacketBiomeIDChange(chunk, world, new HashedBlockPosition(pos)), world.provider.getDimension(), pos, 256); 45 | } 46 | 47 | /** 48 | * @author sk2048 49 | */ 50 | @Overwrite 51 | public static void changeBiome(World world, int biomeId, Chunk chunk, BlockPos pos) { 52 | changeBiome(world, biomeId, pos); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/advancedrocketry/MixinPacketBiomeIDChange.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.advancedrocketry; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.entity.player.EntityPlayer; 6 | import net.minecraft.world.chunk.Chunk; 7 | import org.dimdev.jeid.INewChunk; 8 | import net.minecraftforge.fml.relauncher.Side; 9 | import net.minecraftforge.fml.relauncher.SideOnly; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Overwrite; 12 | import org.spongepowered.asm.mixin.Pseudo; 13 | import org.spongepowered.asm.mixin.Shadow; 14 | import org.spongepowered.asm.mixin.injection.At; 15 | import org.spongepowered.asm.mixin.injection.Inject; 16 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 17 | import zmaster587.advancedRocketry.AdvancedRocketry; 18 | import zmaster587.advancedRocketry.network.PacketBiomeIDChange; 19 | import zmaster587.libVulpes.util.HashedBlockPosition; 20 | 21 | @Pseudo 22 | @Mixin(PacketBiomeIDChange.class) 23 | public class MixinPacketBiomeIDChange { 24 | @Shadow 25 | Chunk chunk; 26 | @Shadow 27 | int worldId, xPos, zPos; 28 | @Shadow 29 | HashedBlockPosition pos; 30 | 31 | int[] intArray; 32 | 33 | @Inject(method = "()V", at = @At("RETURN")) 34 | public void onConstructed(CallbackInfo ci) { 35 | intArray = new int[256]; 36 | } 37 | 38 | /** 39 | * @author sk2048 40 | */ 41 | @Overwrite(remap = false) 42 | public void write(ByteBuf out) { 43 | out.writeInt(worldId); 44 | out.writeInt(chunk.x); 45 | out.writeInt(chunk.z); 46 | out.writeInt(pos.x); 47 | out.writeShort(pos.y); 48 | out.writeInt(pos.z); 49 | 50 | for (int biomeId : ((INewChunk) chunk).getIntBiomeArray()) { 51 | out.writeInt(biomeId); 52 | } 53 | } 54 | 55 | /** 56 | * @author sk2048 57 | */ 58 | @Overwrite(remap = false) 59 | public void readClient(ByteBuf in) { 60 | worldId = in.readInt(); 61 | xPos = in.readInt(); 62 | zPos = in.readInt(); 63 | 64 | pos.x = in.readInt(); 65 | pos.y = in.readShort(); 66 | pos.z = in.readInt(); 67 | 68 | for (int i = 0; i < 256; i++) { 69 | int biomeId = in.readInt(); 70 | intArray[i] = biomeId; 71 | } 72 | } 73 | 74 | 75 | /** 76 | * @author sk2048 77 | */ 78 | @SideOnly(Side.CLIENT) 79 | @Overwrite(remap = false) 80 | public void executeClient(EntityPlayer thePlayer) { 81 | if (thePlayer.world.provider.getDimension() == worldId) { 82 | chunk = thePlayer.world.getChunk(xPos, zPos); 83 | if (chunk.isLoaded()) { 84 | ((INewChunk) chunk).setIntBiomeArray(intArray); 85 | chunk.markDirty(); 86 | thePlayer.world.markBlockRangeForRenderUpdate(pos.getBlockPos(), pos.getBlockPos()); 87 | 88 | if (Minecraft.getMinecraft().gameSettings.particleSetting < 2) 89 | AdvancedRocketry.proxy.spawnParticle("smallLazer", thePlayer.world, pos.x, pos.y, pos.z, 0, 0, 0); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/bewitchment/MixinRitualBiomeShift.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.bewitchment; 2 | 3 | import com.bewitchment.common.item.tool.ItemBoline; 4 | import com.bewitchment.common.ritual.RitualBiomeShift; 5 | import com.bewitchment.common.world.BiomeChangingUtils; 6 | import net.minecraft.entity.player.EntityPlayer; 7 | import net.minecraft.item.ItemStack; 8 | import net.minecraft.network.play.server.SPacketChunkData; 9 | import net.minecraft.util.math.BlockPos; 10 | import net.minecraft.world.World; 11 | import net.minecraft.world.biome.Biome; 12 | import net.minecraft.world.chunk.Chunk; 13 | import net.minecraftforge.items.ItemStackHandler; 14 | import org.spongepowered.asm.mixin.Mixin; 15 | import org.spongepowered.asm.mixin.Overwrite; 16 | import org.spongepowered.asm.mixin.Pseudo; 17 | 18 | @Pseudo 19 | @Mixin(RitualBiomeShift.class) 20 | public class MixinRitualBiomeShift { 21 | @Overwrite(remap = false) 22 | public void onFinished(World world, BlockPos altarPos, BlockPos effectivePos, EntityPlayer caster, ItemStackHandler inventory) { 23 | int id; 24 | Chunk chunk = world.getChunk(effectivePos); 25 | for (int i = 0; i < inventory.getSlots(); i++) { 26 | ItemStack stack = inventory.getStackInSlot(i); 27 | if (stack.getItem() instanceof ItemBoline) { 28 | id = stack.getTagCompound().getInteger("biome_id"); 29 | 30 | //might run thru that only server side, since all client change is done with packets afterwards 31 | int radius = 32; //maybe change that depending on some other stuff? 32 | for (double x = -radius; x < radius; x++) { 33 | for (double z = -radius; z < radius; z++) { 34 | if (Math.sqrt((x * x) + (z * z)) < radius) { 35 | BlockPos pos = effectivePos.add(x, 0, z); 36 | BiomeChangingUtils.setBiome(world, Biome.getBiomeForId(id), pos); 37 | chunk.getWorld().getMinecraftServer().getPlayerList().getPlayers().forEach(p -> p.connection.sendPacket(new SPacketChunkData(chunk, 65535))); 38 | for (i = 0; i < inventory.getSlots(); i++) { 39 | inventory.extractItem(i, 1, false); 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/bewitchment/MixinUtils.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.bewitchment; 2 | 3 | import com.bewitchment.common.world.BiomeChangingUtils; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraft.world.World; 6 | import net.minecraft.world.biome.Biome; 7 | import net.minecraft.world.chunk.Chunk; 8 | import net.minecraftforge.fml.common.network.NetworkRegistry; 9 | import org.dimdev.jeid.INewChunk; 10 | import org.dimdev.jeid.network.BiomeChangeMessage; 11 | import org.dimdev.jeid.network.MessageManager; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Overwrite; 14 | import org.spongepowered.asm.mixin.Pseudo; 15 | 16 | @Pseudo 17 | @Mixin(BiomeChangingUtils.class) 18 | public class MixinUtils { 19 | @Overwrite 20 | public static void setBiome(World world, Biome biome, BlockPos pos) { 21 | Chunk chunk = world.getChunk(pos); 22 | ((INewChunk) chunk).getIntBiomeArray()[(pos.getZ() & 0xF) << 4 | pos.getX() & 0xF] = Biome.getIdForBiome(biome); 23 | chunk.markDirty(); 24 | 25 | if (!world.isRemote) { 26 | MessageManager.CHANNEL.sendToAllAround( 27 | new BiomeChangeMessage(pos.getX(), pos.getZ(), Biome.getIdForBiome(biome)), 28 | new NetworkRegistry.TargetPoint(world.provider.getDimension(), pos.getX(), 128.0D, pos.getZ(), 128.0D) 29 | ); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/biomesoplenty/MixinBOPCommand.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.biomesoplenty; 2 | 3 | import biomesoplenty.common.command.BOPCommand; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Pseudo; 6 | import org.spongepowered.asm.mixin.injection.Constant; 7 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 8 | 9 | @Pseudo 10 | @Mixin(BOPCommand.class) 11 | public abstract class MixinBOPCommand { 12 | @ModifyConstant(method = "teleportFoundBiome", constant = @Constant(intValue = 255), remap = false) 13 | private int getMaxBiomeID(int oldValue) { 14 | return Integer.MAX_VALUE; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/biomesoplenty/MixinModBiomes.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.biomesoplenty; 2 | 3 | import biomesoplenty.common.init.ModBiomes; 4 | import net.minecraft.world.biome.Biome; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.Overwrite; 7 | import org.spongepowered.asm.mixin.Pseudo; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | 10 | import java.util.Set; 11 | 12 | @Pseudo 13 | @Mixin(ModBiomes.class) 14 | public abstract class MixinModBiomes { 15 | @Shadow private static int nextBiomeId; 16 | @Shadow private static Set idsReservedInConfig; 17 | 18 | @Overwrite 19 | public static int getNextFreeBiomeId() { 20 | for (int i = nextBiomeId; i < Integer.MAX_VALUE; ++i) { 21 | if (Biome.getBiome(i) == null && !idsReservedInConfig.contains(i)) { 22 | nextBiomeId = i + 1; 23 | return i; 24 | } 25 | } 26 | throw new RuntimeException("Out of biome IDs (>Integer.MAX_INT), report to JustEnoughIDs"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/biometweaker/MixinBiomeColorMappings.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.biometweaker; 2 | 3 | import me.superckl.biometweaker.util.BiomeColorMappings; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.injection.Constant; 6 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 7 | 8 | @Mixin(BiomeColorMappings.class) 9 | public class MixinBiomeColorMappings { 10 | @ModifyConstant(method = "getColorForBiome", constant = @Constant(intValue = 0xFF), remap = false) 11 | private static int getBitMask(int oldValue) { 12 | return 0xFFFFFFFF; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/biometweaker/MixinBiomeHelper.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.biometweaker; 2 | 3 | import me.superckl.biometweaker.util.BiomeHelper; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.injection.Constant; 6 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 7 | 8 | @Mixin(BiomeHelper.class) 9 | public class MixinBiomeHelper { 10 | @ModifyConstant(method = "getNextFreeBiomeId", constant = @Constant(intValue = 0xFF), remap = false) 11 | private static int getMaxBiomeId(int oldValue) { 12 | return 0xFFFFFFFF; 13 | } 14 | 15 | @ModifyConstant(method = "getNextFreeBiomeId", constant = @Constant(intValue = 0x100), remap = false) 16 | private static int getLoopUpperLimit(int oldValue) { 17 | return 0x7FFFFFFF; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/biometweaker/MixinCommandSetBiome.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.biometweaker; 2 | 3 | import me.superckl.biometweaker.server.command.CommandSetBiome; 4 | import net.minecraft.command.ICommandSender; 5 | import net.minecraft.server.MinecraftServer; 6 | import net.minecraft.util.math.BlockPos; 7 | import net.minecraft.util.math.ChunkPos; 8 | import net.minecraft.util.text.Style; 9 | import net.minecraft.util.text.TextComponentTranslation; 10 | import net.minecraft.util.text.TextFormatting; 11 | import net.minecraft.world.World; 12 | import net.minecraft.world.biome.Biome; 13 | import net.minecraft.world.chunk.Chunk; 14 | import net.minecraftforge.fml.common.network.NetworkRegistry; 15 | import org.dimdev.jeid.INewChunk; 16 | import org.dimdev.jeid.Utils; 17 | import org.dimdev.jeid.network.BiomeArrayMessage; 18 | import org.dimdev.jeid.network.BiomeChangeMessage; 19 | import org.dimdev.jeid.network.MessageManager; 20 | import org.spongepowered.asm.mixin.Mixin; 21 | import org.spongepowered.asm.mixin.injection.At; 22 | import org.spongepowered.asm.mixin.injection.Inject; 23 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 24 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture; 25 | 26 | import java.util.Arrays; 27 | 28 | @Mixin(CommandSetBiome.class) 29 | public class MixinCommandSetBiome { 30 | @Inject(method = "func_184881_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/chunk/Chunk;func_76605_m()[B", remap = false), locals = LocalCapture.CAPTURE_FAILHARD, remap = false) 31 | private void setBiomeArrayElement(MinecraftServer server, ICommandSender sender, String args[], CallbackInfo ci, BlockPos coord, World world, Biome gen, Integer i, int id, boolean blocks, int count, int x, int z, int realX, int realZ, Chunk chunk) { 32 | Utils.LOGGER.info("setting biome at {}, {}", x, z); 33 | ((INewChunk) chunk).getIntBiomeArray()[(z & 0xF) << 4 | x & 0xF] = id; 34 | MessageManager.CHANNEL.sendToAllTracking(new BiomeChangeMessage(x, z, id), new NetworkRegistry.TargetPoint(world.provider.getDimension(), coord.getX(), coord.getY(), coord.getZ(), 256)); 35 | } 36 | 37 | @Inject(method = "func_184881_a", at = @At(value = "INVOKE", target = "Ljava/util/Arrays;fill([BB)V"), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, remap = false) 38 | private void setBiomeArray(MinecraftServer server, ICommandSender sender, String args[], CallbackInfo ci, BlockPos coord, World world, Biome gen, Integer i, int id, boolean blocks, int count, byte biomeArray[]) { 39 | final int[] intBiomeArray = new int[256]; 40 | Arrays.fill(intBiomeArray, id); 41 | ChunkPos chunkPos = new ChunkPos(coord); 42 | 43 | for (int x = chunkPos.x - i; x <= chunkPos.x + i; x++) { 44 | for (int z = chunkPos.z - i; z <= chunkPos.z + i; z++) { 45 | ((INewChunk) world.getChunk(x, z)).setIntBiomeArray(Arrays.copyOf(intBiomeArray, intBiomeArray.length)); 46 | MessageManager.CHANNEL.sendToAllTracking(new BiomeArrayMessage(x, z, Arrays.copyOf(intBiomeArray, intBiomeArray.length)), new NetworkRegistry.TargetPoint(world.provider.getDimension(), coord.getX(), coord.getY(), coord.getZ(), 256)); 47 | count++; 48 | } 49 | } 50 | 51 | sender.sendMessage(new TextComponentTranslation("biometweaker.msg.setbiome.chunksuccess.text", count, gen.getBiomeName()).setStyle(new Style().setColor(TextFormatting.GOLD))); 52 | 53 | ci.cancel(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/bookshelf/MixinWorldUtils.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.bookshelf; 2 | 3 | import net.darkhax.bookshelf.lib.Constants; 4 | import net.darkhax.bookshelf.util.WorldUtils; 5 | import net.minecraft.util.math.BlockPos; 6 | import net.minecraft.world.World; 7 | import net.minecraft.world.biome.Biome; 8 | import net.minecraft.world.chunk.Chunk; 9 | import org.dimdev.jeid.INewChunk; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Overwrite; 12 | import org.spongepowered.asm.mixin.Pseudo; 13 | 14 | import java.util.Arrays; 15 | 16 | @Pseudo 17 | @Mixin(WorldUtils.class) 18 | public abstract class MixinWorldUtils { 19 | @Overwrite(remap = false) 20 | public static void setBiomes(World world, BlockPos pos, Biome biome) { 21 | try { 22 | final Chunk chunk = world.getChunk(pos); 23 | final int[] biomes = ((INewChunk) chunk).getIntBiomeArray(); 24 | Arrays.fill(biomes, Biome.getIdForBiome(biome)); 25 | 26 | WorldUtils.updateNearbyChunks(world, chunk, true, true); 27 | } catch (Exception e) { 28 | Constants.LOG.warn(e, "Unable to set biome for Pos: {}, Biome: {}", pos.toString(), biome.getRegistryName()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/creepingnether/MixinCorruptorAbstract.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.creepingnether; 2 | 3 | import com.cutievirus.creepingnether.Ref; 4 | import com.cutievirus.creepingnether.entity.CorruptorAbstract; 5 | import net.minecraft.init.Biomes; 6 | import net.minecraft.util.math.BlockPos; 7 | import net.minecraft.world.World; 8 | import net.minecraft.world.biome.Biome; 9 | import net.minecraft.world.chunk.Chunk; 10 | import net.minecraftforge.fml.common.network.NetworkRegistry; 11 | import org.dimdev.jeid.INewChunk; 12 | import org.dimdev.jeid.network.BiomeChangeMessage; 13 | import org.dimdev.jeid.network.MessageManager; 14 | import org.spongepowered.asm.mixin.Mixin; 15 | import org.spongepowered.asm.mixin.Overwrite; 16 | import org.spongepowered.asm.mixin.Pseudo; 17 | import org.spongepowered.asm.mixin.Shadow; 18 | 19 | @Pseudo 20 | @Mixin(CorruptorAbstract.class) 21 | public abstract class MixinCorruptorAbstract { 22 | @Shadow public abstract Biome getBiome(); 23 | 24 | @Overwrite(remap = false) 25 | public void corruptBiome(World world, BlockPos pos) { 26 | if (!world.isBlockLoaded(pos)) return; 27 | Biome oldBiome = world.getBiome(pos); 28 | if (oldBiome == this.getBiome() || oldBiome != Biomes.HELL && this.getBiome() != Ref.biomeCreepingNether) return; 29 | Chunk chunk = world.getChunk(pos); 30 | ((INewChunk) chunk).getIntBiomeArray()[(pos.getZ() & 15) << 4 | pos.getX() & 15] = Biome.getIdForBiome(this.getBiome()); 31 | if (!world.isRemote) { 32 | MessageManager.CHANNEL.sendToAllAround( 33 | new BiomeChangeMessage(pos.getX(), pos.getZ(), Biome.getIdForBiome(this.getBiome())), 34 | new NetworkRegistry.TargetPoint(world.provider.getDimension(), pos.getX(), 128.0D, pos.getZ(), 128.0D) 35 | ); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/cyclopscore/MixinWorldHelpers.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.cyclopscore; 2 | 3 | import net.minecraft.util.math.BlockPos; 4 | import net.minecraft.world.World; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.chunk.Chunk; 7 | import net.minecraftforge.fml.common.network.NetworkRegistry; 8 | import org.cyclops.cyclopscore.helper.WorldHelpers; 9 | import org.dimdev.jeid.INewChunk; 10 | import org.dimdev.jeid.network.BiomeChangeMessage; 11 | import org.dimdev.jeid.network.MessageManager; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Overwrite; 14 | import org.spongepowered.asm.mixin.Pseudo; 15 | 16 | @Pseudo 17 | @Mixin(WorldHelpers.class) 18 | public class MixinWorldHelpers { 19 | @Overwrite 20 | public static void setBiome(World world, BlockPos pos, Biome biome) { 21 | Chunk chunk = world.getChunk(pos); 22 | ((INewChunk) chunk).getIntBiomeArray()[(pos.getZ() & 0xF) << 4 | pos.getX() & 0xF] = Biome.getIdForBiome(biome); 23 | chunk.markDirty(); 24 | if (!world.isRemote) { 25 | MessageManager.CHANNEL.sendToAllAround( 26 | new BiomeChangeMessage(pos.getX(), pos.getZ(), Biome.getIdForBiome(biome)), 27 | new NetworkRegistry.TargetPoint(world.provider.getDimension(), pos.getX(), 128.0D, pos.getZ(), 128.0D) 28 | ); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/extrautils2/MixinBiomeManip.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.extrautils2; 2 | 3 | import com.rwtema.extrautils2.biome.BiomeManip; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraft.world.World; 6 | import net.minecraft.world.biome.Biome; 7 | import net.minecraft.world.chunk.Chunk; 8 | import net.minecraftforge.fml.common.network.NetworkRegistry; 9 | import org.dimdev.jeid.INewChunk; 10 | import org.dimdev.jeid.network.BiomeChangeMessage; 11 | import org.dimdev.jeid.network.MessageManager; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Overwrite; 14 | import org.spongepowered.asm.mixin.Pseudo; 15 | 16 | @Pseudo 17 | @Mixin(BiomeManip.class) 18 | public class MixinBiomeManip { 19 | @Overwrite 20 | public static void setBiome(World world, Biome biome, BlockPos pos) { 21 | Chunk chunk = world.getChunk(pos); 22 | ((INewChunk) chunk).getIntBiomeArray()[(pos.getZ() & 0xF) << 4 | pos.getX() & 0xF] = Biome.getIdForBiome(biome); 23 | chunk.markDirty(); 24 | if (!world.isRemote) { 25 | MessageManager.CHANNEL.sendToAllAround( 26 | new BiomeChangeMessage(pos.getX(), pos.getZ(), Biome.getIdForBiome(biome)), 27 | new NetworkRegistry.TargetPoint(world.provider.getDimension(), pos.getX(), 128.0D, pos.getZ(), 128.0D) 28 | ); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/extrautils2/MixinWorldProviderSpecialDim.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.extrautils2; 2 | 3 | import com.rwtema.extrautils2.dimensions.workhousedim.WorldProviderSpecialDim; 4 | import net.minecraft.world.chunk.Chunk; 5 | import net.minecraft.world.gen.ChunkProviderServer; 6 | import org.dimdev.jeid.INewChunk; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Pseudo; 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 org.spongepowered.asm.mixin.injection.callback.LocalCapture; 13 | 14 | import java.util.Arrays; 15 | 16 | @Pseudo 17 | @Mixin(WorldProviderSpecialDim.class) 18 | public class MixinWorldProviderSpecialDim { 19 | @Inject(method = "generate", at = @At(target = "Lnet/minecraft/world/chunk/Chunk;setTerrainPopulated(Z)V", value = "INVOKE"), locals = LocalCapture.CAPTURE_FAILSOFT) 20 | private static void setChunkIntBiomeArray(int x, int z, ChunkProviderServer chunkProvider, Object generator, CallbackInfo ci, Chunk chunk, int idForBiome) { 21 | Arrays.fill(((INewChunk) chunk).getIntBiomeArray(), idForBiome); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/gaiadimension/MixinGenLayerGDRiverMix.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.gaiadimension; 2 | 3 | import androsa.gaiadimension.world.layer.GenLayerGDRiverMix; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Pseudo; 6 | import org.spongepowered.asm.mixin.injection.Constant; 7 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 8 | 9 | @Pseudo 10 | @Mixin(GenLayerGDRiverMix.class) 11 | public class MixinGenLayerGDRiverMix { 12 | @ModifyConstant(method = "func_75904_a", constant = @Constant(intValue = 255), remap = false) 13 | private int getBitMask(int oldValue) { 14 | return 0xFFFFFFFF; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/geographicraft/MixinDimensionManager.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.geographicraft; 2 | 3 | import climateControl.DimensionManager; 4 | import net.minecraft.init.Biomes; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.chunk.Chunk; 7 | import org.dimdev.jeid.INewChunk; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Overwrite; 10 | import org.spongepowered.asm.mixin.Pseudo; 11 | 12 | @Pseudo 13 | @Mixin(DimensionManager.class) 14 | public class MixinDimensionManager { 15 | @Overwrite(remap = false) 16 | private boolean hasOnlySea(Chunk tested) { 17 | for (int biome : ((INewChunk) tested).getIntBiomeArray()) { 18 | if (biome != 0 && biome != Biome.getIdForBiome(Biomes.DEEP_OCEAN)) { 19 | return false; 20 | } 21 | } 22 | 23 | return true; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/hammercore/MixinWorldLocation.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.hammercore; 2 | 3 | import com.zeitheron.hammercore.utils.WorldLocation; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraft.world.World; 6 | import net.minecraft.world.biome.Biome; 7 | import net.minecraft.world.chunk.Chunk; 8 | import net.minecraftforge.fml.common.network.NetworkRegistry; 9 | import org.dimdev.jeid.INewChunk; 10 | import org.dimdev.jeid.network.BiomeChangeMessage; 11 | import org.dimdev.jeid.network.MessageManager; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Overwrite; 14 | import org.spongepowered.asm.mixin.Shadow; 15 | 16 | @Mixin(WorldLocation.class) 17 | public class MixinWorldLocation { 18 | @Shadow private World world; 19 | @Shadow private BlockPos pos; 20 | 21 | /** 22 | * 23 | * @author sk2048 24 | */ 25 | @Overwrite(remap = false) 26 | public void setBiome(Biome biome) { 27 | Chunk chunk = this.world.getChunk(this.pos); 28 | ((INewChunk) chunk).getIntBiomeArray()[(this.pos.getZ() & 0xF) << 4 | this.pos.getX() & 0xF] = Biome.getIdForBiome(biome); 29 | chunk.markDirty(); 30 | if (!this.world.isRemote) { 31 | MessageManager.CHANNEL.sendToAllAround( 32 | new BiomeChangeMessage(this.pos.getX(), this.pos.getZ(), Biome.getIdForBiome(biome)), 33 | new NetworkRegistry.TargetPoint(this.world.provider.getDimension(), this.pos.getX(), 128.0D, this.pos.getZ(), 128.0D) 34 | ); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/journeymap/MixinChunkMD.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.journeymap; 2 | 3 | import journeymap.client.model.ChunkMD; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.chunk.Chunk; 7 | import org.dimdev.jeid.INewChunk; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Overwrite; 10 | import org.spongepowered.asm.mixin.Pseudo; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | 13 | import javax.annotation.Nullable; 14 | 15 | @Pseudo 16 | @Mixin(ChunkMD.class) 17 | public abstract class MixinChunkMD { 18 | 19 | @Shadow public abstract Chunk getChunk(); 20 | 21 | /** 22 | * 23 | * @param pos 24 | * @return 25 | */ 26 | @Overwrite(remap = false) 27 | @Nullable 28 | public Biome getBiome(BlockPos pos) { 29 | Chunk chunk = this.getChunk(); 30 | int[] biomeArray = ((INewChunk) chunk).getIntBiomeArray(); 31 | int biomeId = biomeArray[(pos.getZ() & 0xF) << 4 | pos.getX() & 0xF]; 32 | if (biomeId == 0xFFFFFFFF) { 33 | Biome biome = chunk.getWorld().getBiomeProvider().getBiome(pos, null); 34 | 35 | if (biome == null) { 36 | return null; 37 | } 38 | biomeId = Biome.getIdForBiome(biome); 39 | biomeArray[(pos.getZ() & 0xF) << 4 | pos.getX() & 0xF] = biomeId; 40 | } 41 | 42 | return Biome.getBiome(biomeId); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/mystcraft/MixinBiomeReplacer.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.mystcraft; 2 | 3 | import com.xcompwiz.mystcraft.symbol.symbols.SymbolFloatingIslands; 4 | import net.minecraft.world.biome.Biome; 5 | import net.minecraft.world.chunk.Chunk; 6 | import org.dimdev.jeid.INewChunk; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Overwrite; 9 | import org.spongepowered.asm.mixin.Pseudo; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | 12 | import java.util.Arrays; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | 16 | @Pseudo 17 | @Mixin(SymbolFloatingIslands.BiomeReplacer.class) 18 | public class MixinBiomeReplacer { 19 | @Shadow private HashMap, boolean[]> chunks; 20 | @Shadow private Biome biome; 21 | 22 | @Overwrite(remap = false) 23 | public void finalizeChunk(Chunk chunk, int chunkX, int chunkZ) { 24 | boolean[] modified = chunks.remove(Arrays.asList(chunkX, chunkZ)); 25 | 26 | if (modified != null) { 27 | int[] biomes = ((INewChunk) chunk).getIntBiomeArray(); 28 | 29 | for(int coords = 0; coords < modified.length; ++coords) { 30 | if (modified[coords]) { 31 | biomes[coords] = Biome.getIdForBiome(biome); 32 | } 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/thaumcraft/MixinUtils.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.thaumcraft; 2 | 3 | import net.minecraft.util.math.BlockPos; 4 | import net.minecraft.world.World; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraftforge.fml.common.network.NetworkRegistry; 7 | import org.dimdev.jeid.INewChunk; 8 | import org.dimdev.jeid.network.BiomeChangeMessage; 9 | import org.dimdev.jeid.network.MessageManager; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Overwrite; 12 | import org.spongepowered.asm.mixin.Pseudo; 13 | import thaumcraft.common.lib.utils.Utils; 14 | 15 | @Pseudo 16 | @Mixin(Utils.class) 17 | public class MixinUtils { 18 | @Overwrite 19 | public static void setBiomeAt(World world, BlockPos pos, Biome biome, boolean sync) { 20 | if (biome == null) return; 21 | 22 | INewChunk newChunk = (INewChunk) world.getChunk(pos); 23 | int[] array = newChunk.getIntBiomeArray(); 24 | array[(pos.getX() & 15) << 4 | pos.getZ() & 15] = Biome.getIdForBiome(biome) & 255; 25 | newChunk.setIntBiomeArray(array); 26 | 27 | if (sync && !world.isRemote) { 28 | NetworkRegistry.TargetPoint point = new NetworkRegistry.TargetPoint(world.provider.getDimension(), pos.getX(), world.getHeight(pos).getY(), pos.getZ(), 32.0D); 29 | MessageManager.CHANNEL.sendToAllAround(new BiomeChangeMessage(pos.getX(), pos.getZ(), Biome.getIdForBiome(biome)), point); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/thebetweenlands/MixinBlockSpreadingDeath.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.thebetweenlands; 2 | 3 | import net.minecraft.util.math.BlockPos; 4 | import net.minecraft.world.World; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.chunk.Chunk; 7 | import org.dimdev.jeid.INewChunk; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Pseudo; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Inject; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 13 | import thebetweenlands.common.block.terrain.BlockSpreadingDeath; 14 | 15 | @Pseudo 16 | @Mixin(BlockSpreadingDeath.class) 17 | public class MixinBlockSpreadingDeath { 18 | @Inject(method = "convertBiome", at = @At("HEAD"), cancellable = true, remap = false) 19 | private void convertBiomes(World world, BlockPos pos, Biome biome, CallbackInfo ci) { 20 | Chunk chunk = world.getChunk(pos); 21 | ((INewChunk) chunk).getIntBiomeArray()[(pos.getZ() & 15) << 4 | pos.getX() & 15] = Biome.getIdForBiome(biome); 22 | chunk.markDirty(); 23 | ci.cancel(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/thebetweenlands/MixinGenLayerVoronoiZoomInstanced.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.thebetweenlands; 2 | 3 | import org.spongepowered.asm.mixin.Mixin; 4 | import org.spongepowered.asm.mixin.Pseudo; 5 | import org.spongepowered.asm.mixin.injection.Constant; 6 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 7 | import thebetweenlands.common.world.gen.layer.GenLayerVoronoiZoomInstanced; 8 | 9 | @Pseudo 10 | @Mixin(GenLayerVoronoiZoomInstanced.class) 11 | public abstract class MixinGenLayerVoronoiZoomInstanced { 12 | @ModifyConstant(method = "func_75904_a", constant = @Constant(intValue = 255), remap = false) 13 | private int getBitMask(int oldValue) { 14 | return 0xFFFFFFFF; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/tofucraft/MixinGenLayerRiverMix.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.tofucraft; 2 | 3 | import cn.mcmod.tofucraft.world.gen.layer.GenLayerRiverMix; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Pseudo; 6 | import org.spongepowered.asm.mixin.injection.Constant; 7 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 8 | 9 | @Pseudo 10 | @Mixin(GenLayerRiverMix.class) 11 | public class MixinGenLayerRiverMix { 12 | @ModifyConstant(method = "func_75904_a", constant = @Constant(intValue = 255), remap = false) 13 | private int getBitMask(int oldValue) { 14 | return 0xFFFFFFFF; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/tofucraft/MixinGenLayerTofuVoronoiZoom.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.tofucraft; 2 | 3 | import cn.mcmod.tofucraft.world.gen.layer.GenLayerTofuVoronoiZoom; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Pseudo; 6 | import org.spongepowered.asm.mixin.injection.Constant; 7 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 8 | 9 | @Pseudo 10 | @Mixin(GenLayerTofuVoronoiZoom.class) 11 | public class MixinGenLayerTofuVoronoiZoom { 12 | @ModifyConstant(method = "func_75904_a", constant = @Constant(intValue = 255), remap = false) 13 | private int getBitMask(int oldValue) { 14 | return 0xFFFFFFFF; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/tropicraft/MixinGenLayerTropiVoronoiZoom.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.tropicraft; 2 | 3 | import net.tropicraft.core.common.worldgen.genlayer.GenLayerTropiVoronoiZoom; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Pseudo; 6 | import org.spongepowered.asm.mixin.injection.Constant; 7 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 8 | 9 | @Pseudo 10 | @Mixin(GenLayerTropiVoronoiZoom.class) 11 | public class MixinGenLayerTropiVoronoiZoom { 12 | @ModifyConstant(method = "func_75904_a", constant = @Constant(intValue = 255), remap = false) 13 | private int getBitMask(int oldValue) { 14 | return 0xFFFFFFFF; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/twilightforest/MixinBlockTFMagicLogSpecial.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.twilightforest; 2 | 3 | import net.minecraft.util.math.BlockPos; 4 | import net.minecraft.world.World; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.chunk.Chunk; 7 | import net.minecraftforge.fml.common.network.NetworkRegistry; 8 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 9 | import org.dimdev.jeid.INewChunk; 10 | import org.dimdev.jeid.network.BiomeChangeMessage; 11 | import org.dimdev.jeid.network.MessageManager; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Overwrite; 14 | import org.spongepowered.asm.mixin.Pseudo; 15 | import org.spongepowered.asm.mixin.injection.At; 16 | import org.spongepowered.asm.mixin.injection.Inject; 17 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 18 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture; 19 | import twilightforest.block.BlockTFMagicLogSpecial; 20 | 21 | import java.util.Random; 22 | 23 | @Pseudo 24 | @Mixin(BlockTFMagicLogSpecial.class) 25 | public class MixinBlockTFMagicLogSpecial { 26 | /** 27 | * For versions 3.9 and later 28 | */ 29 | @Overwrite(remap = false) 30 | private void sendChangedBiome(World world, BlockPos pos, Biome biome) { 31 | IMessage message = new BiomeChangeMessage(pos.getX(), pos.getZ(), Biome.getIdForBiome(biome)); 32 | MessageManager.CHANNEL.sendToAllAround(message, new NetworkRegistry.TargetPoint(world.provider.getDimension(), pos.getX(), 128.0D, pos.getZ(), 128.0D)); 33 | } 34 | 35 | @Inject(method = "doTreeOfTransformationEffect", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/chunk/Chunk;getBiomeArray()[B"), locals = LocalCapture.CAPTURE_FAILSOFT) 36 | private void onChangeBiome(World world, BlockPos pos, Random rand, CallbackInfo ci, Biome targetBiome, int i, BlockPos dPos, Biome biomeAt, Chunk chunkAt) { 37 | ((INewChunk) chunkAt).getIntBiomeArray()[(dPos.getZ() & 15) << 4 | (dPos.getX() & 15)] = Biome.getIdForBiome(targetBiome); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/twilightforest/MixinBlockTFMagicLogSpecial_Old.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.twilightforest; 2 | 3 | import net.minecraft.util.math.BlockPos; 4 | import net.minecraft.world.World; 5 | import net.minecraft.world.biome.Biome; 6 | import net.minecraft.world.chunk.Chunk; 7 | import net.minecraftforge.fml.common.network.NetworkRegistry; 8 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 9 | import org.dimdev.jeid.INewChunk; 10 | import org.dimdev.jeid.network.BiomeChangeMessage; 11 | import org.dimdev.jeid.network.MessageManager; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Overwrite; 14 | import org.spongepowered.asm.mixin.Pseudo; 15 | import org.spongepowered.asm.mixin.injection.At; 16 | import org.spongepowered.asm.mixin.injection.Inject; 17 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 18 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture; 19 | import twilightforest.biomes.TFBiomes; 20 | import twilightforest.block.BlockTFMagicLogSpecial; 21 | 22 | import java.util.Random; 23 | 24 | @Pseudo 25 | @Mixin(BlockTFMagicLogSpecial.class) 26 | public class MixinBlockTFMagicLogSpecial_Old { 27 | /** 28 | * For versions upto and including 3.8 29 | */ 30 | @Overwrite(remap = false) 31 | private void sendChangedBiome(World world, BlockPos pos) { 32 | IMessage message = new BiomeChangeMessage(pos.getX(), pos.getZ(), Biome.getIdForBiome(TFBiomes.enchantedForest)); 33 | MessageManager.CHANNEL.sendToAllAround(message, new NetworkRegistry.TargetPoint(world.provider.getDimension(), pos.getX(), 128.0D, pos.getZ(), 128.0D)); 34 | } 35 | 36 | @Inject(method = "doTreeOfTransformationEffect", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/chunk/Chunk;getBiomeArray()[B"), locals = LocalCapture.CAPTURE_FAILSOFT) 37 | private void onChangeBiome(World world, BlockPos pos, Random rand, CallbackInfo ci, int i, BlockPos dPos, Biome biomeAt, Chunk chunkAt) { 38 | ((INewChunk) chunkAt).getIntBiomeArray()[(dPos.getZ() & 15) << 4 | (dPos.getX() & 15)] = Biome.getIdForBiome(TFBiomes.enchantedForest); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/twilightforest/MixinGenLayerTFRiverMix.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.twilightforest; 2 | 3 | import org.spongepowered.asm.mixin.Mixin; 4 | import org.spongepowered.asm.mixin.Pseudo; 5 | import org.spongepowered.asm.mixin.injection.Constant; 6 | import org.spongepowered.asm.mixin.injection.ModifyConstant; 7 | import twilightforest.world.layer.GenLayerTFRiverMix; 8 | 9 | @Pseudo 10 | @Mixin(GenLayerTFRiverMix.class) 11 | public class MixinGenLayerTFRiverMix { 12 | @ModifyConstant(method = "func_75904_a", constant = @Constant(intValue = 255), remap = false) 13 | private int getBitMask(int oldValue) { 14 | return 0xFFFFFFFF; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/twilightforest/TwilightMixinPlugin.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.twilightforest; 2 | 3 | import net.minecraftforge.fml.common.Loader; 4 | import net.minecraftforge.fml.common.ModContainer; 5 | import org.dimdev.jeid.Utils; 6 | import org.objectweb.asm.tree.ClassNode; 7 | import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; 8 | import org.spongepowered.asm.mixin.extensibility.IMixinInfo; 9 | 10 | import java.util.List; 11 | import java.util.Set; 12 | 13 | public class TwilightMixinPlugin implements IMixinConfigPlugin { 14 | 15 | @Override 16 | public void onLoad(String s) {} 17 | 18 | @Override 19 | public String getRefMapperConfig() { return null; } 20 | 21 | @Override 22 | public boolean shouldApplyMixin(String s, String s1) { 23 | for (ModContainer mod : Loader.instance().getModList()) { 24 | if (mod.getModId().equals("twilightforest")) { 25 | if (s1.equals("org.dimdev.jeid.mixin.modsupport.twilightforest.MixinBlockTFMagicLogSpecial_Old")) { 26 | if (Integer.parseInt(mod.getVersion().split("[.]")[2]) < 689) { 27 | Utils.LOGGER.info("Older TwilightForest version (<689). Using mixin: " + s1); 28 | return true; 29 | } else { 30 | return false; 31 | } 32 | } else if (s1.equals("org.dimdev.jeid.mixin.modsupport.twilightforest.MixinBlockTFMagicLogSpecial")) { 33 | if (Integer.parseInt(mod.getVersion().split("[.]")[2]) > 689) { 34 | Utils.LOGGER.info("Newer TwilightForest version (>689). Using mixin: " + s1); 35 | return true; 36 | } else { 37 | return false; 38 | } 39 | } else { 40 | return true; 41 | } 42 | } 43 | } 44 | return false; 45 | } 46 | 47 | @Override 48 | public void acceptTargets(Set set, Set set1) { 49 | 50 | } 51 | 52 | @Override 53 | public List getMixins() { 54 | return null; 55 | } 56 | 57 | @Override 58 | public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { 59 | 60 | } 61 | 62 | @Override 63 | public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/mixin/modsupport/worldedit/MixinBaseBlock.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.mixin.modsupport.worldedit; 2 | 3 | import com.sk89q.worldedit.blocks.BaseBlock; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Overwrite; 6 | import org.spongepowered.asm.mixin.Pseudo; 7 | import org.spongepowered.asm.mixin.Shadow; 8 | 9 | @Pseudo 10 | @Mixin(BaseBlock.class) 11 | public class MixinBaseBlock { 12 | @Shadow private short id; 13 | 14 | @Overwrite(remap = false) 15 | protected final void internalSetId(int id) { 16 | if (id > Short.MAX_VALUE) { 17 | throw new IllegalArgumentException("Can't have a block ID above 32767 (" + id + " given)"); 18 | } else if (id < 0) { 19 | throw new IllegalArgumentException("Can't have a block ID below 0"); 20 | } else { 21 | this.id = (short)id; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/network/BiomeArrayMessage.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.network; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.multiplayer.WorldClient; 6 | import net.minecraft.network.PacketBuffer; 7 | import net.minecraft.util.math.BlockPos; 8 | import net.minecraft.world.chunk.Chunk; 9 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 10 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 11 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 12 | import org.dimdev.jeid.INewChunk; 13 | 14 | public class BiomeArrayMessage implements IMessage { 15 | private int chunkX; 16 | private int chunkZ; 17 | private int[] biomeArray; 18 | 19 | public BiomeArrayMessage() {} 20 | 21 | public BiomeArrayMessage(int chunkX, int chunkZ, int[] biomeArray) { 22 | this.chunkX = chunkX; 23 | this.chunkZ = chunkZ; 24 | this.biomeArray = biomeArray; 25 | } 26 | 27 | @Override 28 | public void fromBytes(ByteBuf byteBuf) { 29 | PacketBuffer packetBuffer = new PacketBuffer(byteBuf); 30 | chunkX = packetBuffer.readVarInt(); 31 | chunkZ = packetBuffer.readVarInt(); 32 | biomeArray = packetBuffer.readVarIntArray(); 33 | } 34 | 35 | @Override 36 | public void toBytes(ByteBuf byteBuf) { 37 | PacketBuffer packetBuffer = new PacketBuffer(byteBuf); 38 | packetBuffer.writeVarInt(chunkX); 39 | packetBuffer.writeVarInt(chunkZ); 40 | packetBuffer.writeVarIntArray(biomeArray); 41 | } 42 | 43 | public static class Handler implements IMessageHandler { 44 | @Override 45 | public IMessage onMessage(BiomeArrayMessage message, MessageContext ctx) { 46 | Minecraft.getMinecraft().addScheduledTask(() -> { 47 | WorldClient world = Minecraft.getMinecraft().world; 48 | Chunk chunk = world.getChunk(message.chunkX, message.chunkZ); 49 | ((INewChunk) chunk).setIntBiomeArray(message.biomeArray); 50 | world.markBlockRangeForRenderUpdate(new BlockPos(chunk.getPos().getXStart(), 0, chunk.getPos().getZStart()), new BlockPos(chunk.getPos().getXEnd(), 0, chunk.getPos().getZEnd())); 51 | }); 52 | return null; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/network/BiomeChangeMessage.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.network; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.multiplayer.WorldClient; 6 | import net.minecraft.network.PacketBuffer; 7 | import net.minecraft.util.math.BlockPos; 8 | import net.minecraft.world.chunk.Chunk; 9 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 10 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 11 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 12 | import org.dimdev.jeid.INewChunk; 13 | 14 | public class BiomeChangeMessage implements IMessage { 15 | private int x; 16 | private int z; 17 | private int biomeId; 18 | 19 | public BiomeChangeMessage() {} 20 | 21 | public BiomeChangeMessage(int x, int z, int biomeId) { 22 | this.x = x; 23 | this.z = z; 24 | this.biomeId = biomeId; 25 | } 26 | 27 | @Override 28 | public void fromBytes(ByteBuf byteBuf) { 29 | PacketBuffer packetBuffer = new PacketBuffer(byteBuf); 30 | x = packetBuffer.readVarInt(); 31 | z = packetBuffer.readVarInt(); 32 | biomeId = packetBuffer.readVarInt(); 33 | } 34 | 35 | @Override 36 | public void toBytes(ByteBuf byteBuf) { 37 | PacketBuffer packetBuffer = new PacketBuffer(byteBuf); 38 | packetBuffer.writeVarInt(x); 39 | packetBuffer.writeVarInt(z); 40 | packetBuffer.writeVarInt(biomeId); 41 | } 42 | 43 | public static class Handler implements IMessageHandler { 44 | @Override 45 | public IMessage onMessage(BiomeChangeMessage message, MessageContext ctx) { 46 | Minecraft.getMinecraft().addScheduledTask(() -> { 47 | WorldClient world = Minecraft.getMinecraft().world; 48 | Chunk chunk = world.getChunk(new BlockPos(message.x, 0, message.z)); 49 | ((INewChunk) chunk).getIntBiomeArray()[(message.z & 15) << 4 | message.x & 15] = message.biomeId; 50 | world.markBlockRangeForRenderUpdate(new BlockPos(message.x, 0, message.z), new BlockPos(message.x, 0, message.z)); 51 | }); 52 | return null; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/dimdev/jeid/network/MessageManager.java: -------------------------------------------------------------------------------- 1 | package org.dimdev.jeid.network; 2 | 3 | import net.minecraftforge.fml.common.network.NetworkRegistry; 4 | import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; 5 | import net.minecraftforge.fml.relauncher.Side; 6 | 7 | public class MessageManager { 8 | public static final SimpleNetworkWrapper CHANNEL = NetworkRegistry.INSTANCE.newSimpleChannel("jeid"); 9 | 10 | public static void init() { 11 | CHANNEL.registerMessage(BiomeArrayMessage.Handler.class, BiomeArrayMessage.class, 0, Side.CLIENT); 12 | CHANNEL.registerMessage(BiomeChangeMessage.Handler.class, BiomeChangeMessage.class, 1, Side.CLIENT); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/jeid_at.cfg: -------------------------------------------------------------------------------- 1 | # Enchantment IDs 2 | public net.minecraft.enchantment.EnchantmentHelper$IModifier -------------------------------------------------------------------------------- /src/main/resources/assets/jeid/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DimensionalDevelopment/JustEnoughIDs/4d7f1fc4ff3afd965e698f98f998c1d5072518db/src/main/resources/assets/jeid/logo.png -------------------------------------------------------------------------------- /src/main/resources/mcmod.info: -------------------------------------------------------------------------------- 1 | { 2 | "modListVersion": 2, 3 | "modList": [ 4 | { 5 | "modid": "jeid", 6 | "name": "JustEnoughIDs", 7 | "description": "Use the 1.13 chunk format in 1.12 to remove block, item, and biome ID limits.\n\nThanks to zabi94 for helping getting potions and enchants extended.", 8 | "version": "${version}", 9 | "mcversion": "1.12.2", 10 | "url": "https://minecraft.curseforge.com/projects/jeid", 11 | "authorList": [ 12 | "Runemoro", 13 | "ZombieHDGaming" 14 | ], 15 | "logoFile": "/assets/jeid/logo.png", 16 | "parent": "", 17 | "screenshots": [], 18 | "dependencies": [] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/main/resources/mixins.jeid.core.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "org.dimdev.jeid.mixin.core", 3 | "required": true, 4 | "refmap": "mixins.jeid.refmap.json", 5 | "target": "@env(DEFAULT)", 6 | "minVersion": "0.6", 7 | "compatibilityLevel": "JAVA_8", 8 | "mixins": [ 9 | "MixinGameData", 10 | "MixinStatList", 11 | "MixinBlockStateContainer", 12 | "MixinAnvilChunkLoader", 13 | "MixinBlock", 14 | "MixinChunk", 15 | "MixinSPacketChunkData", 16 | "MixinGenLayerVoronoiZoom", 17 | "MixinChunkPrimer", 18 | "MixinChunkProviderServer", 19 | "MixinWorldInfo", 20 | "MixinEnchantmentHelper", 21 | "MixinItemEnchantedBook" 22 | ], 23 | "client": [ 24 | "client.MixinChunk", 25 | "client.MixinRenderGlobal", 26 | "client.MixinWorldSummary" 27 | ], 28 | "injectors": { 29 | "maxShiftBy": 10 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/resources/mixins.jeid.init.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "org.dimdev.jeid.mixin.init", 3 | "required": true, 4 | "refmap": "mixins.jeid.refmap.json", 5 | "target": "@env(INIT)", 6 | "minVersion": "0.6", 7 | "compatibilityLevel": "JAVA_8", 8 | "mixins": [ 9 | "JEIDMixinLoader" 10 | ], 11 | "client": [], 12 | "injectors": { 13 | "maxShiftBy": 10 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/resources/mixins.jeid.modsupport.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "org.dimdev.jeid.mixin.modsupport", 3 | "required": true, 4 | "refmap": "mixins.jeid.refmap.json", 5 | "target": "@env(DEFAULT)", 6 | "minVersion": "0.6", 7 | "compatibilityLevel": "JAVA_8", 8 | "mixins": [ 9 | "abyssalcraft.MixinBiomeUtil", 10 | "advancedrocketry.MixinBiomeHandler", 11 | "advancedrocketry.MixinPacketBiomeIDChange", 12 | "bewitchment.MixinRitualBiomeShift", 13 | "bewitchment.MixinUtils", 14 | "biomesoplenty.MixinBOPCommand", 15 | "biomesoplenty.MixinModBiomes", 16 | "biometweaker.MixinBiomeColorMappings", 17 | "biometweaker.MixinBiomeHelper", 18 | "biometweaker.MixinCommandSetBiome", 19 | "bookshelf.MixinWorldUtils", 20 | "creepingnether.MixinCorruptorAbstract", 21 | "cyclopscore.MixinWorldHelpers", 22 | "extrautils2.MixinBiomeManip", 23 | "extrautils2.MixinWorldProviderSpecialDim", 24 | "gaiadimension.MixinGenLayerGDRiverMix", 25 | "geographicraft.MixinDimensionManager", 26 | "hammercore.MixinWorldLocation", 27 | "journeymap.MixinChunkMD", 28 | "mystcraft.MixinBiomeReplacer", 29 | "thaumcraft.MixinUtils", 30 | "thebetweenlands.MixinBlockSpreadingDeath", 31 | "thebetweenlands.MixinGenLayerVoronoiZoomInstanced", 32 | "tofucraft.MixinGenLayerRiverMix", 33 | "tofucraft.MixinGenLayerTofuVoronoiZoom", 34 | "tropicraft.MixinGenLayerTropiVoronoiZoom", 35 | "worldedit.MixinBaseBlock" 36 | ], 37 | "client": [], 38 | "injectors": { 39 | "maxShiftBy": 10 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/resources/mixins.jeid.twilightforest.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "org.dimdev.jeid.mixin.modsupport.twilightforest", 3 | "plugin": "org.dimdev.jeid.mixin.modsupport.twilightforest.TwilightMixinPlugin", 4 | "required": true, 5 | "refmap": "mixins.jeid.refmap.json", 6 | "target": "@env(DEFAULT)", 7 | "minVersion": "0.6", 8 | "compatibilityLevel": "JAVA_8", 9 | "mixins": [ 10 | "MixinBlockTFMagicLogSpecial", 11 | "MixinBlockTFMagicLogSpecial_Old", 12 | "MixinGenLayerTFRiverMix" 13 | ], 14 | "client": [], 15 | "injectors": { 16 | "maxShiftBy": 10 17 | } 18 | } -------------------------------------------------------------------------------- /src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "pack_format": 3, 4 | "description": "JustEnoughIDs" 5 | } 6 | } 7 | --------------------------------------------------------------------------------