diff --git a/README.md b/README.md index 3829996..3eba116 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,58 @@ # IC2 Patcher Fixes several bugs in IndustrialCraft2 using [binary patches](http://javaxdelta.sourceforge.net). -Note that you **may NOT distribute** any decompiled code generated by this tool. +Note that you **may NOT distribute** any decompiled code generated by this tool. For more information, see [IC2's license](https://forum.industrial-craft.net/thread/9843-mc-1-7-ic%C2%B2-v-2-1-x-2-2-x-experimental/). ### List of patches -- Fixed issue [0002205](https://bt.industrial-craft.net/view.php?id=2205): Jetpack mode on Quantum Suit not disableable - To toggle the jetpack, press the *mode switch key* while *sneaking* -- Corrected the Near-Depleted Uranium Cell's recipe output size to 8 -- Fixed issue [0002749](https://bt.industrial-craft.net/view.php?id=2749): Batch Crafter Dupe -- Fixed issue [0002745](https://bt.industrial-craft.net/view.php?id=2745): Crash the world with Electrolyzer, Fluid Pulling Upgrade and Pump Attachment -- Fixed issue [0002717](https://bt.industrial-craft.net/view.php?id=2717): Client crashed when connect a bronze fluid pipe with an ie fluid pipe -- Fixed issue [0002586](https://bt.industrial-craft.net/view.php?id=2586): Nightvision Goggles can break -- Night vision goggles now clear their effect immediately after disabling -- Corrected the specs of the Energy and Lapotron crystals in the classic profile -- Fixed a bug which displayed all non-fluid classic cell recipes in the [same recipe category](https://imgur.com/a/qkECYYD) -- Fixed issue [0002752](https://bt.industrial-craft.net/view.php?id=2752): Bug with Industrial Craft 2 textures - Obscuration now replaces textures instead of rendering another layer over them -- Fixed issue [0002701](https://bt.industrial-craft.net/view.php?id=2701): Crop-Matron and Crop Harvester ignoring Transformer Upgrades - -### Creating patches - -#### Setting up -1. Clone the repository -2. Run the `setup` gradle task - This will set up both `IC2-Base` and `IC2-Patched` projects, which contain clean and patched code respectively. - Note that while this code will compile, it's *highly unstable* and not suitable for playing. +You can find lists of patches for each supported IC2 Version [here](). + +#### Currently supported versions: +- IC2-2.8.221 and above +- IC2-2.8.164 -#### Generating patches -After making changes to the code, run the `generatePatches` task of the `IC2-Patched` project to generate the patches. -This has to be done **manually** every time you make changes. +# Contribution -#### Building & Exporting -Run `gradlew build`to build the patcher. The resulting jar will be located in the `build/libs` folder. -Remember that the jar build by the `jar` task **will NOT work** outside the dev environment. +### Setting up the dev environment +1. Clone the repository. +2. Run the `setup` gradle task found in `env setup`. + This will set up both `IC2-Base` and `IC2-Patched` projects, which contain clean and patched code respectively. + Note that while this code will compile, it's *highly unstable* and might not work on your OS / IDE. +
+ +### Generating patches for currently supported versions of IC2 +After making changes to the code, run the `generatePatches` task of the `IC2-Patched` project to generate the patches for currently set IC2 version. This has to be done **manually** every time you make changes. +
+ +### Generating patches for non-supported versions of IC2 +To add support for a new version of IC2: +1. Change IC2 version in `gradle.properties` file. +2. Create a new Folder in root of project 'IC2-Base' and 'IC2-Patched' with name in the following format:
+ `patches[minVersion,maxVersion]` where: + - minVersion - Minimum version of IC2 that those patches are meant to be applied to, inclusive. + - maxVersion - Maximum version of IC2 that those patches are meant to be applied to, exclusive. + + Example: `patches[2.8.164, 2.8.165]` -> Folder for patches for IC2 version 2.8.164-exp112 + It's recommended to copy over patches from the closest supported version and resolve issues from there. +3. Run the `setup` gradle task found in `env setup`. + 1. If `IC2-Base` project fails to compile, resolve all issues generated by Compiler and run the `generatePatches` gradle task found in `IC2-Base` project. + This will generate patches that will be applied after IC2-Base de-compilation step. + Take note that while this process will allow the code to compile, the code might have been decompiled incorrectly in the first place, and cause the dev env game to not launch successfully. It's recommended to use the other decompilation tool to diagnose and correct the mistake. + 2. If `IC2-Patched` project fails to compile, remove patches that aren't getting applied properly, and if relevant, port them to the currently used IC2 version. +4. After making changes to the code, run `generatePatches` task of the `IC2-Patched` project to generate the patches. +
+ +### Building & Exporting +1. Run the `generateBinPatches` task of the IC2-Patched project for each version you have done changes to. + 1. Make sure there aren't overlapping folders from previously generated patches! +2. Run `gradlew build`to build the patcher. + The resulting jar will be located in the `build/libs` folder. + Remember that the jar build by the `jar` task **will NOT work** outside the dev environment.
The Unlicense Logo
-

Licensing

+

Licensing

-All code is licensed under **The Unlicense**, except for `mods.su5ed.ic2patcher.asm.BinPatchManager`, which is a modified version +All code is licensed under **The Unlicense**, except for `mods.su5ed.ic2patcher.asm.BinPatchManager`, which is a modified version of MinecraftForge's [ClassPatchManager](https://github.com/MinecraftForge/MinecraftForge/blob/1.12.x/src/main/java/net/minecraftforge/fml/common/patcher/ClassPatchManager.java) class, and is licensed under the **GNU Lesser General Public License version 2.1** diff --git a/build.gradle.kts b/build.gradle.kts index f6ef7b8..d173658 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,8 +2,7 @@ import fr.brouillard.oss.jgitver.GitVersionCalculator import fr.brouillard.oss.jgitver.Strategies import net.minecraftforge.gradle.common.util.RunConfig import wtf.gofancy.fancygradle.script.extensions.deobf -import net.minecraftforge.gradle.patcher.task.GenerateBinPatches -import wtf.gofancy.fancygradle.patch.Patch +import net.minecraftforge.gradle.patcher.tasks.GenerateBinPatches buildscript { dependencies { @@ -15,7 +14,7 @@ plugins { `java-library` `maven-publish` idea - id("net.minecraftforge.gradle") version "5.0.11" + id("net.minecraftforge.gradle") version "5.1.+" id("de.undercouch.download") version "4.1.1" id("wtf.gofancy.fancygradle") version "1.1.+" } @@ -57,10 +56,11 @@ minecraft { fancyGradle { patches { - Patch.RESOURCES - Patch.COREMODS - Patch.CODE_CHICKEN_LIB - Patch.ASM + asm + codeChickenLib + coremods + resources + mergetool } } @@ -78,7 +78,7 @@ repositories { maven { // IC2 Repository name = "ic2" - url = uri("https://maven.ic2.player.to/") + url = uri("https://maven2.ic2.player.to/") } } @@ -86,8 +86,8 @@ dependencies { minecraft(group = "net.minecraftforge", name = "forge", version = "1.12.2-${versionForge}") implementation(project(":IC2-Patched")) -// implementation(fg.deobf(group = "mezz.jei", name = "jei_1.12.2", version = versionJEI)) - compileOnly(fg.deobf(group = "mezz.jei", name = "jei_1.12.2", version = versionJEI)) + implementation(fg.deobf(group = "mezz.jei", name = "jei_1.12.2", version = versionJEI)) +// compileOnly(fg.deobf(group = "mezz.jei", name = "jei_1.12.2", version = versionJEI)) } tasks { @@ -116,22 +116,22 @@ tasks { exclude("patches"); } from(generateDevBinPatches.output) - - manifest { + + manifest { attributes( "FMLCorePlugin" to "mods.su5ed.ic2patcher.asm.PatcherFMLPlugin", "FMLCorePluginContainsFMLMod" to true ) } } - + register("releaseJar") { archiveClassifier.set("") val generateBinPatches = project(":IC2-Patched").tasks.getByName("generateBinPatches") dependsOn(generateBinPatches) - + from(sourceSets.main.get().output) - manifest { + manifest { attributes( "FMLCorePlugin" to "mods.su5ed.ic2patcher.asm.PatcherFMLPlugin", "FMLCorePluginContainsFMLMod" to true @@ -146,7 +146,11 @@ tasks { whenTaskAdded { if (name.startsWith("prepareRun")) { + dependsOn(project(":IC2-Patched").tasks.getByName("patchRunJar")) dependsOn("devJar") + dependsOn("patchModifyClassPath") + dependsOn("patchGenerateObfToSrg") + dependsOn("patchExtractMappingsZip") } } } @@ -157,7 +161,7 @@ reobf { } } -artifacts { +artifacts { archives(tasks.getByName("releaseJar")) } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 30d399d..7454180 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d403218..8049c68 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Mon Sep 14 12:28:28 PDT 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip diff --git a/gradlew b/gradlew index 91a7e26..744e882 100644 --- a/gradlew +++ b/gradlew @@ -1,4 +1,20 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## ## @@ -6,20 +22,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +64,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -37,36 +72,17 @@ case "`uname`" in Darwin* ) darwin=true ;; - MINGW* ) + MSYS* | MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -90,7 +106,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -110,11 +126,13 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" @@ -138,27 +156,30 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 8a0b282..107acd3 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -8,20 +24,23 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,34 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/projects/IC2-Base/build.gradle.kts b/projects/IC2-Base/build.gradle.kts index efa4542..a62b393 100644 --- a/projects/IC2-Base/build.gradle.kts +++ b/projects/IC2-Base/build.gradle.kts @@ -1,8 +1,8 @@ import codechicken.diffpatch.util.PatchMode import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import net.minecraftforge.gradle.common.task.JarExec -import net.minecraftforge.gradle.patcher.task.TaskApplyPatches -import net.minecraftforge.gradle.patcher.task.TaskGeneratePatches +import net.minecraftforge.gradle.common.tasks.JarExec +import net.minecraftforge.gradle.patcher.tasks.ApplyPatches +import net.minecraftforge.gradle.patcher.tasks.GeneratePatches import org.apache.commons.io.FileUtils import java.io.BufferedReader import java.io.FileOutputStream @@ -53,10 +53,10 @@ minecraft { tasks { register("decompileIC2") { group = taskGroup - tool = "net.minecraftforge:forgeflower:$versionForgeFlower" + tool.set("net.minecraftforge:forgeflower:$versionForgeFlower") val input = ic2.singleFile.absolutePath outputs.file(decompiledJar) - args = arrayOf("-din=1", "-rbr=1", "-dgs=1", "-asc=1", "-rsy=1", "-iec=1", "-jvn=1", "-log=TRACE", input, decompiledJar.absolutePath) + args.set(listOf("-din=1", "-rbr=1", "-dgs=1", "-asc=1", "-rsy=1", "-iec=1", "-jvn=1", "-log=TRACE", input, decompiledJar.absolutePath)) } register("applyStyle") { @@ -66,16 +66,16 @@ tasks { output.set(processedJar) } - register("applyPatches") { + register("applyPatches") { group = taskGroup dependsOn("applyStyle") - base = processedJar + base.set(processedJar) + + patches.set(getPatchesDirectory()) + rejects.set(File(buildDir, "$name/rejects.zip")) + output.set(patchedJar) + patchMode.set(PatchMode.OFFSET) - patches = getPatchesDirectory() - rejects = File(buildDir, "$name/rejects.zip") - output = patchedJar - patchMode = PatchMode.OFFSET - isPrintSummary = true } @@ -129,20 +129,20 @@ tasks { from(sourceSets.main.get().allSource) } - register("generatePatches") { + register("generatePatches") { group = taskGroup val sourceJar = getByName("sourceJarW-ODep") var outputDir = getPatchesDirectory() dependsOn(sourceJar, "applyStyle") - base = processedJar - modified = sourceJar.archiveFile.get().asFile - output = outputDir + base.set(processedJar) + modified.set(sourceJar.archiveFile.get().asFile) + output.set(outputDir) isPrintSummary = true - + doLast { val outputPath = outputDir.toPath() Files.walk(outputPath) - .filter { path -> + .filter { path -> val relative = outputPath.relativize(path).toString() relative.isNotEmpty() && (!relative.startsWith("ic2") || relative.startsWith("ic2\\profiles") || relative.startsWith("ic2\\sounds")) && path.toFile().isDirectory } @@ -192,7 +192,7 @@ repositories { mavenCentral() maven { name = "ic2" - url = uri("https://maven.ic2.player.to/") + url = uri("https://maven2.ic2.player.to/") } maven { name = "Progwml6 maven" diff --git a/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch b/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch new file mode 100644 index 0000000..d84d71f --- /dev/null +++ b/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch @@ -0,0 +1,44 @@ +--- a/ic2/core/block/machine/container/ContainerBatchCrafter.java ++++ b/ic2/core/block/machine/container/ContainerBatchCrafter.java +@@ -12,7 +12,6 @@ + import java.util.Collections; + import java.util.List; + import net.minecraft.entity.player.EntityPlayer; +-import net.minecraft.inventory.Slot; + import net.minecraft.item.ItemStack; + + public class ContainerBatchCrafter extends ContainerElectricMachine { +@@ -26,10 +25,9 @@ + for(int j = 0; j < 3; ++j) { + this.addSlotToContainer(new SlotHologramSlot(tileEntity.craftingGrid, j + i * 3, 30 + j * 18, 17 + i * 18, 1, new SlotHologramSlot.ChangeCallback() { + public void onChanged(int index) { +- if (((TileEntityBatchCrafter)ContainerBatchCrafter.this.base).hasWorld() && !((TileEntityBatchCrafter)ContainerBatchCrafter.this.base).getWorld().isRemote) { +- ((TileEntityBatchCrafter)ContainerBatchCrafter.this.base).matrixChange(index); ++ if (ContainerBatchCrafter.this.base.hasWorld() && !ContainerBatchCrafter.this.base.getWorld().isRemote) { ++ ContainerBatchCrafter.this.base.matrixChange(index); + } +- + } + })); + } +@@ -49,15 +47,15 @@ + } + + protected ItemStack handlePlayerSlotShiftClick(EntityPlayer player, ItemStack sourceItemStack) { +- Tuple.T2, ? extends TIntCollection> t2 = StackUtil.balanceStacks(((TileEntityBatchCrafter)this.base).ingredients, ((TileEntityBatchCrafter)this.base).acceptPredicate, StackUtil.getSlotsFromInv(((TileEntityBatchCrafter)this.base).ingredients), Collections.singleton(sourceItemStack)); +- TIntIterator tintiterator = ((TIntCollection)t2.b).iterator(); ++ Tuple.T2, ? extends TIntCollection> t2 = StackUtil.balanceStacks(this.base.ingredients, this.base.acceptPredicate, StackUtil.getSlotsFromInv(this.base.ingredients), Collections.singleton(sourceItemStack)); ++ TIntIterator tintiterator = t2.b.iterator(); + +- while(tintiterator.hasNext()) { ++ while (tintiterator.hasNext()) { + int i = tintiterator.next(); +- ((Slot)this.inventorySlots.get(this.indexToSlot.get(i))).onSlotChanged(); ++ this.inventorySlots.get(this.indexToSlot.get(i)).onSlotChanged(); + } + +- sourceItemStack = ((List)t2.a).isEmpty() ? StackUtil.emptyStack : (ItemStack)((List)t2.a).get(0); ++ sourceItemStack = t2.a.isEmpty() ? StackUtil.emptyStack : t2.a.get(0); + return sourceItemStack; + } + diff --git a/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch b/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch index 3072ad5..e126501 100644 --- a/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch +++ b/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch @@ -1,5 +1,14 @@ --- a/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java +++ b/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java +@@ -121,7 +121,7 @@ + }; + this.acceptPredicate = new Predicate>() { + public boolean apply(Tuple.T2 input) { +- return TileEntityBatchCrafter.this.ingredientsRow[((Integer)input.b).intValue()].accepts((ItemStack)input.a); ++ return TileEntityBatchCrafter.this.ingredientsRow[input.b].accepts(input.a); + } + }; + this.recipe = null; @@ -132,8 +132,9 @@ this.progress = 0; this.guiProgress = 0.0F; diff --git a/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/network/DataEncoder.java.patch b/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/network/DataEncoder.java.patch index f55f95a..a44dc40 100644 --- a/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/network/DataEncoder.java.patch +++ b/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/network/DataEncoder.java.patch @@ -1,1101 +1,63 @@ --- a/ic2/core/network/DataEncoder.java +++ b/ic2/core/network/DataEncoder.java -@@ -9,9 +9,12 @@ - import ic2.core.IC2; - import ic2.core.block.comp.TileEntityComponent; - import ic2.core.block.invslot.InvSlot; -+import ic2.core.network.GrowingBuffer; - import ic2.core.util.StackUtil; - import ic2.core.util.Tuple; - import ic2.core.util.Util; -+import java.io.DataInput; -+import java.io.DataOutput; - import java.io.IOException; - import java.lang.reflect.Array; - import java.util.Arrays; -@@ -42,704 +45,760 @@ - import net.minecraftforge.fluids.FluidTank; - - public final class DataEncoder { -- private static final Map, DataEncoder.EncodedType> classToTypeCache = Collections., DataEncoder.EncodedType>synchronizedMap(new IdentityHashMap()); -- private static final Map, INetworkCustomEncoder> classToAddonType = Collections., INetworkCustomEncoder>synchronizedMap(new IdentityHashMap()); -+ private static final Map, EncodedType> classToTypeCache = Collections.synchronizedMap(new IdentityHashMap()); -+ private static final Map, INetworkCustomEncoder> classToAddonType = Collections.synchronizedMap(new IdentityHashMap()); - - public static void encode(GrowingBuffer os, Object o) throws IOException { - try { -- encode(os, o, true); -- } catch (IllegalArgumentException illegalargumentexception) { -- IC2.platform.displayError(illegalargumentexception, "An unknown data type was attempted to be encoded for sending through\nmultiplayer.\nThis could happen due to a bug."); -- } -- -+ DataEncoder.encode(os, o, true); -+ } -+ catch (IllegalArgumentException e) { -+ IC2.platform.displayError(e, "An unknown data type was attempted to be encoded for sending through\nmultiplayer.\nThis could happen due to a bug.", new Object[0]); -+ } - } - - public static void encode(IGrowingBuffer os, Object o, boolean withType) throws IOException { -- DataEncoder.EncodedType dataencoder$encodedtype = typeFromObject(o); -+ EncodedType type = DataEncoder.typeFromObject(o); - if (withType) { -- os.writeByte(idFromType(dataencoder$encodedtype)); -+ os.writeByte(DataEncoder.idFromType(type)); - } -- -- switch(dataencoder$encodedtype) { -- case Addon: -- case UnSafeAddon: -- assert o != null; -- -- INetworkCustomEncoder inetworkcustomencoder = classToAddonType.get(o.getClass()); -- if (inetworkcustomencoder == null) { -- throw new IllegalStateException("Cannot encode an object without an encoder! Type was " + o.getClass()); -+ return; -+ /*switch (type) { -+ case Addon: -+ case UnSafeAddon: { -+ assert (o != null); -+ INetworkCustomEncoder ince = classToAddonType.get(o.getClass()); -+ if (ince == null) { -+ throw new IllegalStateException("Cannot encode an object without an encoder! Type was " + o.getClass()); -+ } -+ os.writeString(o.getClass().getName()); -+ ince.encode(os, o); -+ break; - } -- -- os.writeString(o.getClass().getName()); -- inetworkcustomencoder.encode(os, o); -- break; -- case Array: -- Class oclass = o.getClass().getComponentType(); -- int j = Array.getLength(o); -- if (oclass == Object.class && j > 0) { -- boolean flag = false; -- Class oclass1 = null; -- -- label203: -- for(int k = 0; k < j; ++k) { -- Object object = Array.get(o, k); -- if (oclass1 == null) { -- if (object instanceof Enum) { -- oclass1 = ((Enum)object).getDeclaringClass(); -- flag = true; -- } else if (object != null) { -- oclass1 = object.getClass(); -- -- assert oclass1 != Object.class; -+ case Array: { -+ Object value; -+ int i; -+ Class componentClass = o.getClass().getComponentType(); -+ int len = Array.getLength(o); -+ if (componentClass == Object.class && len > 0) { -+ boolean isEnum = false; -+ Class target = null; -+ block40: for (i = 0; i < len; ++i) { -+ value = Array.get(o, i); -+ if (target == null) { -+ if (value instanceof Enum) { -+ target = ((Enum)value).getDeclaringClass(); -+ isEnum = true; -+ continue; -+ } -+ if (value == null) continue; -+ target = value.getClass(); -+ assert (target != Object.class); -+ continue; - } -- } else if (object != null) { -- Class oclass2 = object.getClass(); -- if (oclass2 != oclass1 && !oclass1.isAssignableFrom(oclass2)) { -- if (flag || object instanceof Enum) { -- throw new IllegalArgumentException("Array of mixed enum entries"); -- } -- -- while((oclass1 = oclass1.getSuperclass()) != Object.class) { -- if (oclass1.isAssignableFrom(oclass2)) { -- continue label203; -- } -- } -- -- ++k; -- -- while(k < j) { -- if (Array.get(o, k) instanceof Enum) { -+ if (value != null) { -+ Class valueClass = value.getClass(); -+ if (valueClass != target && !target.isAssignableFrom(valueClass)) { -+ if (isEnum || value instanceof Enum) { - throw new IllegalArgumentException("Array of mixed enum entries"); - } -- -- ++k; -+ while ((target = target.getSuperclass()) != Object.class) { -+ if (!target.isAssignableFrom(valueClass)) continue; -+ continue block40; -+ } -+ ++i; -+ while (i < len) { -+ if (Array.get(o, i) instanceof Enum) { -+ throw new IllegalArgumentException("Array of mixed enum entries"); -+ } -+ ++i; -+ } -+ target = Object.class; -+ break; - } -- -- oclass1 = Object.class; -- break; -- } else { -- assert flag == (object instanceof Enum); -+ assert (isEnum == value instanceof Enum); -+ continue; - } -- } else if (flag) { -+ if (!isEnum) continue; - throw new IllegalArgumentException("Enum array with null entry"); - } -- } -- -- oclass = oclass1; -- } -- -- DataEncoder.EncodedType dataencoder$encodedtype1 = typeFromClass(oclass); -- os.writeByte(idFromType(dataencoder$encodedtype1)); -- os.writeBoolean(oclass.isPrimitive()); -- if (dataencoder$encodedtype1 == DataEncoder.EncodedType.Addon || dataencoder$encodedtype1 == DataEncoder.EncodedType.UnSafeAddon || dataencoder$encodedtype1 == DataEncoder.EncodedType.Enum) { -- os.writeString(oclass.getName()); -- } -- -- os.writeVarInt(j); -- boolean flag1 = false; -- -- for(int l = 0; l < j; ++l) { -- Object object1 = Array.get(o, l); -- if (object1 == null || typeFromClass(object1.getClass()) != dataencoder$encodedtype1) { -- flag1 = true; -- break; -- } -- } -- -- os.writeBoolean(flag1); -- -- for(int i1 = 0; i1 < j; ++i1) { -- encode(os, Array.get(o, i1), flag1); -- } -- break; -- case Block: -- encode(os, Util.getName((Block)o), false); -- break; -- case BlockPos: -- BlockPos blockpos = (BlockPos)o; -- os.writeInt(blockpos.getX()); -- os.writeInt(blockpos.getY()); -- os.writeInt(blockpos.getZ()); -- break; -- case Boolean: -- os.writeBoolean(((Boolean)o).booleanValue()); -- break; -- case Byte: -- os.writeByte(((Byte)o).byteValue()); -- break; -- case Character: -- os.writeChar(((Character)o).charValue()); -- break; -- case ChunkPos: -- ChunkPos chunkpos = (ChunkPos)o; -- os.writeInt(chunkpos.x); -- os.writeInt(chunkpos.z); -- break; -- case Collection: -- encode(os, ((Collection)o).toArray(), false); -- break; -- case Component: -- NBTTagCompound nbttagcompound = ((TileEntityComponent)o).writeToNbt(); -- encode(os, nbttagcompound == null ? new NBTTagCompound() : nbttagcompound, false); -- break; -- case CropCard: -- CropCard cropcard = (CropCard)o; -- os.writeString(cropcard.getOwner()); -- os.writeString(cropcard.getId()); -- break; -- case Double: -- os.writeDouble(((Double)o).doubleValue()); -- break; -- case ElectrolyzerRecipe: -- IElectrolyzerRecipeManager.ElectrolyzerRecipe ielectrolyzerrecipemanager$electrolyzerrecipe = (IElectrolyzerRecipeManager.ElectrolyzerRecipe)o; -- os.writeInt(ielectrolyzerrecipemanager$electrolyzerrecipe.inputAmount); -- os.writeInt(ielectrolyzerrecipemanager$electrolyzerrecipe.EUaTick); -- os.writeInt(ielectrolyzerrecipemanager$electrolyzerrecipe.ticksNeeded); -- IElectrolyzerRecipeManager.ElectrolyzerOutput[] aielectrolyzerrecipemanager$electrolyzeroutput = ielectrolyzerrecipemanager$electrolyzerrecipe.outputs; -- os.writeByte(aielectrolyzerrecipemanager$electrolyzeroutput.length); -- -- for(IElectrolyzerRecipeManager.ElectrolyzerOutput ielectrolyzerrecipemanager$electrolyzeroutput : aielectrolyzerrecipemanager$electrolyzeroutput) { -- os.writeString(ielectrolyzerrecipemanager$electrolyzeroutput.fluidName); -- os.writeInt(ielectrolyzerrecipemanager$electrolyzeroutput.fluidAmount); -- os.writeByte(ielectrolyzerrecipemanager$electrolyzeroutput.tankDirection.getIndex()); -- } -- -- return; -- case Enchantment: -- encode(os, Enchantment.REGISTRY.getNameForObject((Enchantment)o), false); -- break; -- case Enum: -- os.writeVarInt(((Enum)o).ordinal()); -- break; -- case Float: -- os.writeFloat(((Float)o).floatValue()); -- break; -- case Fluid: -- os.writeString(((Fluid)o).getName()); -- break; -- case FluidStack: -- FluidStack fluidstack = (FluidStack)o; -- encode(os, fluidstack.getFluid(), false); -- os.writeInt(fluidstack.amount); -- encode(os, fluidstack.tag, true); -- break; -- case FluidTank: -- FluidTank fluidtank = (FluidTank)o; -- encode(os, fluidtank.getFluid(), true); -- os.writeInt(fluidtank.getCapacity()); -- break; -- case GameProfile: -- GameProfile gameprofile = (GameProfile)o; -- encode(os, gameprofile.getId(), true); -- os.writeString(gameprofile.getName()); -- break; -- case Integer: -- os.writeInt(((Integer)o).intValue()); -- break; -- case InvSlot: -- InvSlot invslot = (InvSlot)o; -- ItemStack[] aitemstack = new ItemStack[invslot.size()]; -- -- for(int i = 0; i < invslot.size(); ++i) { -- aitemstack[i] = invslot.get(i); -- } -- -- encode(os, aitemstack, false); -- break; -- case Item: -- encode(os, Util.getName((Item)o), false); -- break; -- case ItemStack: -- ItemStack itemstack = (ItemStack)o; -- if (StackUtil.isEmpty(itemstack)) { -- os.writeByte(0); -- } else { -- os.writeByte(StackUtil.getSize(itemstack)); -- encode(os, itemstack.getItem(), false); -- os.writeShort(itemstack.getItemDamage()); -- encode(os, itemstack.getTagCompound(), true); -- } -- break; -- case Long: -- os.writeLong(((Long)o).longValue()); -- break; -- case NBTTagCompound: -- CompressedStreamTools.write((NBTTagCompound)o, os); -- break; -- case Null: -- if (!withType) { -+ componentClass = target; -+ } -+ EncodedType componentType = DataEncoder.typeFromClass(componentClass); -+ os.writeByte(DataEncoder.idFromType(componentType)); -+ os.writeBoolean(componentClass.isPrimitive()); -+ if (componentType == EncodedType.Addon || componentType == EncodedType.UnSafeAddon || componentType == EncodedType.Enum) { -+ os.writeString(componentClass.getName()); -+ } -+ os.writeVarInt(len); -+ boolean anyTypeMismatch = false; -+ for (i = 0; i < len; ++i) { -+ value = Array.get(o, i); -+ if (value != null && DataEncoder.typeFromClass(value.getClass()) == componentType) continue; -+ anyTypeMismatch = true; -+ break; -+ } -+ os.writeBoolean(anyTypeMismatch); -+ for (i = 0; i < len; ++i) { -+ DataEncoder.encode(os, Array.get(o, i), anyTypeMismatch); -+ } -+ break; -+ } -+ case Block: { -+ DataEncoder.encode(os, Util.getName((Block)o), false); -+ break; -+ } -+ case BlockPos: { -+ BlockPos pos = (BlockPos)o; -+ os.writeInt(pos.getX()); -+ os.writeInt(pos.getY()); -+ os.writeInt(pos.getZ()); -+ break; -+ } -+ case Boolean: { -+ os.writeBoolean((Boolean)o); -+ break; -+ } -+ case Byte: { -+ os.writeByte(((Byte)o).byteValue()); -+ break; -+ } -+ case Character: { -+ os.writeChar(((Character)o).charValue()); -+ break; -+ } -+ case ChunkPos: { -+ ChunkPos pos = (ChunkPos)o; -+ os.writeInt(pos.x); -+ os.writeInt(pos.z); -+ break; -+ } -+ case Collection: { -+ DataEncoder.encode(os, ((Collection)o).toArray(), false); -+ break; -+ } -+ case Component: { -+ NBTTagCompound nbt = ((TileEntityComponent)o).writeToNbt(); -+ DataEncoder.encode(os, nbt == null ? new NBTTagCompound() : nbt, false); -+ break; -+ } -+ case CropCard: { -+ CropCard cropCard = (CropCard)o; -+ os.writeString(cropCard.getOwner()); -+ os.writeString(cropCard.getId()); -+ break; -+ } -+ case Double: { -+ os.writeDouble((Double)o); -+ break; -+ } -+ case ElectrolyzerRecipe: { -+ IElectrolyzerRecipeManager.ElectrolyzerRecipe recipe = (IElectrolyzerRecipeManager.ElectrolyzerRecipe)o; -+ os.writeInt(recipe.inputAmount); -+ os.writeInt(recipe.EUaTick); -+ os.writeInt(recipe.ticksNeeded); -+ IElectrolyzerRecipeManager.ElectrolyzerOutput[] outputs = recipe.outputs; -+ os.writeByte(outputs.length); -+ for (IElectrolyzerRecipeManager.ElectrolyzerOutput output : outputs) { -+ os.writeString(output.fluidName); -+ os.writeInt(output.fluidAmount); -+ os.writeByte(output.tankDirection.getIndex()); -+ } -+ break; -+ } -+ case Enchantment: { -+ DataEncoder.encode(os, Enchantment.REGISTRY.getNameForObject(((Enchantment)o)), false); -+ break; -+ } -+ case Enum: { -+ os.writeVarInt(((Enum)o).ordinal()); -+ break; -+ } -+ case Float: { -+ os.writeFloat(((Float)o).floatValue()); -+ break; -+ } -+ case Fluid: { -+ os.writeString(((Fluid)o).getName()); -+ break; -+ } -+ case FluidStack: { -+ FluidStack fs = (FluidStack)o; -+ DataEncoder.encode(os, fs.getFluid(), false); -+ os.writeInt(fs.amount); -+ DataEncoder.encode(os, fs.tag, true); -+ break; -+ } -+ case FluidTank: { -+ FluidTank tank = (FluidTank)o; -+ DataEncoder.encode(os, tank.getFluid(), true); -+ os.writeInt(tank.getCapacity()); -+ break; -+ } -+ case GameProfile: { -+ GameProfile gp = (GameProfile)o; -+ DataEncoder.encode(os, gp.getId(), true); -+ os.writeString(gp.getName()); -+ break; -+ } -+ case Integer: { -+ os.writeInt((Integer)o); -+ break; -+ } -+ case InvSlot: { -+ InvSlot slot = (InvSlot)o; -+ ItemStack[] contents = new ItemStack[slot.size()]; -+ for (int i = 0; i < slot.size(); ++i) { -+ contents[i] = slot.get(i); -+ } -+ DataEncoder.encode(os, contents, false); -+ break; -+ } -+ case Item: { -+ DataEncoder.encode(os, Util.getName((Item)o), false); -+ break; -+ } -+ case ItemStack: { -+ ItemStack stack = (ItemStack)o; -+ if (StackUtil.isEmpty(stack)) { -+ os.writeByte(0); -+ break; -+ } -+ os.writeByte(StackUtil.getSize(stack)); -+ DataEncoder.encode(os, stack.getItem(), false); -+ os.writeShort(stack.getItemDamage()); -+ DataEncoder.encode(os, stack.getTagCompound(), true); -+ break; -+ } -+ case Long: { -+ os.writeLong((Long)o); -+ break; -+ } -+ case NBTTagCompound: { -+ CompressedStreamTools.write((NBTTagCompound)((NBTTagCompound)o), (DataOutput)os); -+ break; -+ } -+ case Null: { -+ if (withType) break; - throw new IllegalArgumentException("o has to be non-null without types"); +@@ -391,7 +391,7 @@ + final int i2 = is.readVarInt(); + boolean flag3 = is.readBoolean(); + boolean flag = !dataencoder$encodedtype.threadSafe; +- final Object object; ++ Object object; + if (!flag) { + object = Array.newInstance(oclass1, i2); + } else { +@@ -432,12 +432,13 @@ + return object; } -- break; -- case Object: -- throw new IllegalArgumentException("unhandled class: " + o.getClass()); -- case Potion: -- encode(os, Potion.REGISTRY.getNameForObject((Potion)o), false); -- break; -- case ResourceLocation: -- ResourceLocation resourcelocation = (ResourceLocation)o; -- os.writeString(resourcelocation.getResourceDomain()); -- os.writeString(resourcelocation.getResourcePath()); -- break; -- case Short: -- os.writeShort(((Short)o).shortValue()); -- break; -- case String: -- os.writeString((String)o); -- break; -- case TileEntity: -- TileEntity tileentity = (TileEntity)o; -- encode(os, tileentity.getWorld(), false); -- encode(os, tileentity.getPos(), false); -- break; -- case TupleT2: -- Tuple.T2 t2 = (Tuple.T2)o; -- encode(os, t2.a, true); -- encode(os, t2.b, true); -- break; -- case TupleT3: -- Tuple.T3 t3 = (Tuple.T3)o; -- encode(os, t3.a, true); -- encode(os, t3.b, true); -- encode(os, t3.c, true); -- break; -- case UUID: -- UUID uuid = (UUID)o; -- os.writeLong(uuid.getMostSignificantBits()); -- os.writeLong(uuid.getLeastSignificantBits()); -- break; -- case Vec3: -- Vec3d vec3d = (Vec3d)o; -- os.writeDouble(vec3d.x); -- os.writeDouble(vec3d.y); -- os.writeDouble(vec3d.z); -- break; -- case World: -- os.writeInt(((World)o).provider.getDimension()); -- break; -- default: -- throw new IllegalArgumentException("unhandled type: " + dataencoder$encodedtype); -- } -- -+ case Object: { -+ throw new IllegalArgumentException("unhandled class: " + o.getClass()); -+ } -+ case Potion: { -+ DataEncoder.encode(os, Potion.REGISTRY.getNameForObject(((Potion)o)), false); -+ break; -+ } -+ case ResourceLocation: { -+ ResourceLocation loc = (ResourceLocation)o; -+ os.writeString(loc.getResourceDomain()); -+ os.writeString(loc.getResourcePath()); -+ break; -+ } -+ case Short: { -+ os.writeShort(((Short)o).shortValue()); -+ break; -+ } -+ case String: { -+ os.writeString((String)o); -+ break; -+ } -+ case TileEntity: { -+ TileEntity te = (TileEntity)o; -+ DataEncoder.encode(os, te.getWorld(), false); -+ DataEncoder.encode(os, te.getPos(), false); -+ break; -+ } -+ case TupleT2: { -+ Tuple.T2 t = (Tuple.T2)o; -+ DataEncoder.encode(os, t.a, true); -+ DataEncoder.encode(os, t.b, true); -+ break; -+ } -+ case TupleT3: { -+ Tuple.T3 t = (Tuple.T3)o; -+ DataEncoder.encode(os, t.a, true); -+ DataEncoder.encode(os, t.b, true); -+ DataEncoder.encode(os, t.c, true); -+ break; -+ } -+ case UUID: { -+ UUID uuid = (UUID)o; -+ os.writeLong(uuid.getMostSignificantBits()); -+ os.writeLong(uuid.getLeastSignificantBits()); -+ break; -+ } -+ case Vec3: { -+ Vec3d v = (Vec3d)o; -+ os.writeDouble(v.x); -+ os.writeDouble(v.y); -+ os.writeDouble(v.z); -+ break; -+ } -+ case World: { -+ os.writeInt(((World)o).provider.getDimension()); -+ break; -+ } -+ default: { -+ throw new IllegalArgumentException("unhandled type: " + (Object)((Object)type)); -+ } -+ }*/ - } - public static Object decode(IGrowingBuffer is) throws IOException { - try { -- return decode(is, typeFromId(is.readUnsignedByte())); -- } catch (IllegalArgumentException illegalargumentexception) { -- String s = "An unknown data type was received over multiplayer to be decoded.\nThis could happen due to corrupted data or a bug."; -- IC2.platform.displayError(illegalargumentexception, s); -+ return DataEncoder.decode(is, DataEncoder.typeFromId(is.readByte())); -+ } -+ catch (IllegalArgumentException e) { -+ String msg = "An unknown data type was received over multiplayer to be decoded.\nThis could happen due to corrupted data or a bug."; -+ IC2.platform.displayError(e, msg, new Object[0]); - return null; - } - } ++ Object finalObject = object; + return new DataEncoder.IResolvableValue() { + public Object get() { + Object object3 = Array.newInstance(oclass, i2); - public static T decode(IGrowingBuffer is, Class clazz) throws IOException { -- DataEncoder.EncodedType dataencoder$encodedtype = typeFromClass(clazz); -- if (dataencoder$encodedtype.threadSafe) { -- return (T)decode(is, dataencoder$encodedtype); -- } else { -- throw new IllegalArgumentException("requesting decode for non thread safe type"); -+ EncodedType type = DataEncoder.typeFromClass(clazz); -+ if (type.threadSafe) { -+ return (T)DataEncoder.decode(is, type); - } -+ throw new IllegalArgumentException("requesting decode for non thread safe type"); - } - - public static > T decodeEnum(IGrowingBuffer is, Class clazz) throws IOException { -- int i = ((Integer)decode(is, DataEncoder.EncodedType.Enum)).intValue(); -- T[] at = clazz.getEnumConstants(); -- return (T)(i >= 0 && i < at.length ? at[i] : null); -+ int ordinal = (Integer)DataEncoder.decode(is, EncodedType.Enum); -+ Enum[] values = (Enum[])clazz.getEnumConstants(); -+ return (T)(ordinal >= 0 && ordinal < values.length ? values[ordinal] : null); - } - - public static Object decodeDeferred(GrowingBuffer is, Class clazz) throws IOException { -- DataEncoder.EncodedType dataencoder$encodedtype = typeFromClass(clazz); -- return decode(is, dataencoder$encodedtype); -+ EncodedType type = DataEncoder.typeFromClass(clazz); -+ return DataEncoder.decode((IGrowingBuffer)is, type); - } + for(int l2 = 0; l2 < i2; ++l2) { +- Array.set(object3, l2, DataEncoder.getValue(Array.get(object, l2))); ++ Array.set(object3, l2, DataEncoder.getValue(Array.get(finalObject, l2))); + } -- public static Object decode(final IGrowingBuffer is, DataEncoder.EncodedType type) throws IOException { -- switch(type) { -- case Addon: -- case UnSafeAddon: -- String s = is.readString(); -- final INetworkCustomEncoder inetworkcustomencoder = classToAddonType.get(getClass(s)); -- if (inetworkcustomencoder == null) { -- throw new IllegalStateException("Cannot decode an object without a decoder! Type was " + s); -- } else { -- if (inetworkcustomencoder.isThreadSafe()) { -- return inetworkcustomencoder.decode(is); -- } -+ public static Object decode(final IGrowingBuffer is, EncodedType type) throws IOException { -+ switch (type) { -+ case Addon: -+ case UnSafeAddon: { -+ String aimTypeName = is.readString(); -+ final INetworkCustomEncoder ince = classToAddonType.get(DataEncoder.getClass(aimTypeName)); -+ if (ince == null) { -+ throw new IllegalStateException("Cannot decode an object without a decoder! Type was " + aimTypeName); -+ } -+ if (ince.isThreadSafe()) { -+ return ince.decode(is); -+ } -+ return new IResolvableValue(){ + return object3; +@@ -467,7 +468,7 @@ -- return new DataEncoder.IResolvableValue() { -+ @Override - public Object get() { - try { -- return inetworkcustomencoder.decode(is); -- } catch (IOException ioexception) { -- throw new RuntimeException("Unexpected error", ioexception); -+ return ince.decode(is); -+ } -+ catch (IOException e) { -+ throw new RuntimeException("Unexpected error", e); - } - } - }; - } -- case Array: -- DataEncoder.EncodedType dataencoder$encodedtype = typeFromId(is.readUnsignedByte()); -- boolean flag1 = is.readBoolean(); -- boolean flag2 = dataencoder$encodedtype == DataEncoder.EncodedType.Enum; -- Class oclass1 = flag1 ? unbox(dataencoder$encodedtype.cls) : dataencoder$encodedtype.cls; -- if (oclass1 == null || flag2) { -- assert dataencoder$encodedtype == DataEncoder.EncodedType.Addon || dataencoder$encodedtype == DataEncoder.EncodedType.UnSafeAddon || flag2; -- -- oclass1 = getClass(is.readString()); -- } -- -- final Class oclass = oclass1; -- final int i2 = is.readVarInt(); -- boolean flag3 = is.readBoolean(); -- boolean flag = !dataencoder$encodedtype.threadSafe; -- final Object object; -- if (!flag) { -- object = Array.newInstance(oclass1, i2); -- } else { -- object = new Object[i2]; -- } -- -- if (!flag3) { -- if (flag2) { -- Object[] aobject = oclass1.getEnumConstants(); -- -- assert aobject != null; -- -- for(int k = 0; k < i2; ++k) { -- Array.set(object, k, aobject[((Integer)decode(is, dataencoder$encodedtype)).intValue()]); -+ case Array: { -+ Class component; -+ EncodedType componentType = DataEncoder.typeFromId(is.readUnsignedByte()); -+ boolean primitive = is.readBoolean(); -+ boolean isEnum = componentType == EncodedType.Enum; -+ Class clazz = component = primitive ? DataEncoder.unbox(componentType.cls) : componentType.cls; -+ if (component == null || isEnum) { -+ assert (componentType == EncodedType.Addon || componentType == EncodedType.UnSafeAddon || isEnum); -+ component = DataEncoder.getClass(is.readString()); -+ } -+ final Class componentClass = component; -+ final int len = is.readVarInt(); -+ boolean anyTypeMismatch = is.readBoolean(); -+ boolean needsResolving = !componentType.threadSafe; -+ Object array = !needsResolving ? Array.newInstance(componentClass, len) : new Object[len]; -+ if (!anyTypeMismatch) { -+ if (isEnum) { -+ Object[] constants = componentClass.getEnumConstants(); -+ assert (constants != null); -+ for (int i = 0; i < len; ++i) { -+ Array.set(array, i, constants[(Integer)DataEncoder.decode(is, componentType)]); -+ } -+ } else { -+ for (int i = 0; i < len; ++i) { -+ Array.set(array, i, DataEncoder.decode(is, componentType)); -+ } - } - } else { -- for(int j2 = 0; j2 < i2; ++j2) { -- Array.set(object, j2, decode(is, dataencoder$encodedtype)); -- } -- } -- } else { -- for(int k2 = 0; k2 < i2; ++k2) { -- DataEncoder.EncodedType dataencoder$encodedtype1 = typeFromId(is.readUnsignedByte()); -- if (!dataencoder$encodedtype1.threadSafe && !flag) { -- flag = true; -- if (oclass != Object.class) { -- Object object1 = new Object[i2]; -- System.arraycopy(object, 0, object1, 0, k2); -- object = object1; -- } -- } -- -- Array.set(object, k2, decode(is, dataencoder$encodedtype1)); -- } -- } -- -- if (!flag) { -- return object; -- } -- -- return new DataEncoder.IResolvableValue() { -- public Object get() { -- Object object3 = Array.newInstance(oclass, i2); -- -- for(int l2 = 0; l2 < i2; ++l2) { -- Array.set(object3, l2, DataEncoder.getValue(Array.get(object, l2))); -- } -- -- return object3; -- } -- }; -- case Block: -- return Util.getBlock((ResourceLocation)decode(is, DataEncoder.EncodedType.ResourceLocation)); -- case BlockPos: -- return new BlockPos(is.readInt(), is.readInt(), is.readInt()); -- case Boolean: -- return is.readBoolean(); -- case Byte: -- return is.readByte(); -- case Character: -- return is.readChar(); -- case ChunkPos: -- return new ChunkPos(is.readInt(), is.readInt()); -- case Collection: -- final Object object2 = decode(is, DataEncoder.EncodedType.Array); -- if (object2 instanceof DataEncoder.IResolvableValue) { -- return new DataEncoder.IResolvableValue>() { -- public List get() { -- return Arrays.asList(((DataEncoder.IResolvableValue)object2).get()); -- } -- }; -- } -- -- return Arrays.asList(object2); -- case Component: + return Arrays.asList(object2); + case Component: - return (List)decode(is, DataEncoder.EncodedType.NBTTagCompound); -- case CropCard: -- return Crops.instance.getCropCard(is.readString(), is.readString()); -- case Double: -- return is.readDouble(); -- case ElectrolyzerRecipe: -- int i1 = is.readInt(); -- int j1 = is.readInt(); -- int l1 = is.readInt(); -- byte b1 = is.readByte(); -- IElectrolyzerRecipeManager.ElectrolyzerOutput[] aielectrolyzerrecipemanager$electrolyzeroutput = new IElectrolyzerRecipeManager.ElectrolyzerOutput[b1]; -- -- for(byte b0 = 0; b0 < b1; ++b0) { -- aielectrolyzerrecipemanager$electrolyzeroutput[b0] = new IElectrolyzerRecipeManager.ElectrolyzerOutput(is.readString(), is.readInt(), EnumFacing.getFront(is.readByte())); -- } -- -- return new IElectrolyzerRecipeManager.ElectrolyzerRecipe(i1, j1, l1, aielectrolyzerrecipemanager$electrolyzeroutput); -- case Enchantment: -- return (List)Enchantment.REGISTRY.getObject((ResourceLocation)decode(is, DataEncoder.EncodedType.ResourceLocation)); -- case Enum: -- return is.readVarInt(); -- case Float: -- return is.readFloat(); -- case Fluid: -- return FluidRegistry.getFluid(is.readString()); -- case FluidStack: -- FluidStack fluidstack = new FluidStack((Fluid)decode(is, DataEncoder.EncodedType.Fluid), is.readInt()); -- fluidstack.tag = (NBTTagCompound)decode(is); -- return fluidstack; -- case FluidTank: -- return new FluidTank((FluidStack)decode(is), is.readInt()); -- case GameProfile: -- return new GameProfile((UUID)decode(is), is.readString()); -- case Integer: -- return is.readInt(); -- case InvSlot: -- ItemStack[] aitemstack = (ItemStack[])decode(is, DataEncoder.EncodedType.Array); -- InvSlot invslot = new InvSlot(aitemstack.length); -- -- for(int k1 = 0; k1 < aitemstack.length; ++k1) { -- invslot.put(k1, aitemstack[k1]); -- } -- -- return invslot; -- case Item: -- return Util.getItem((ResourceLocation)decode(is, DataEncoder.EncodedType.ResourceLocation)); -- case ItemStack: -- int l = is.readByte(); -- if (l == 0) { -- return StackUtil.emptyStack; -- } -- -- Item item = (Item)decode(is, Item.class); -- int j = is.readShort(); -- NBTTagCompound nbttagcompound = (NBTTagCompound)decode(is); -- ItemStack itemstack = new ItemStack(item, l, j); -- itemstack.setTagCompound(nbttagcompound); -- return itemstack; -- case Long: -- return is.readLong(); -- case NBTTagCompound: -- return CompressedStreamTools.read(is, NBTSizeTracker.INFINITE); -- case Null: -- return null; -- case Object: -- return (List)(new Object()); -- case Potion: -- return (List)Potion.REGISTRY.getObject((ResourceLocation)decode(is, DataEncoder.EncodedType.ResourceLocation)); -- case ResourceLocation: -- return new ResourceLocation(is.readString(), is.readString()); -- case Short: -- return is.readShort(); -- case String: -- return is.readString(); -- case TileEntity: -- final DataEncoder.IResolvableValue iresolvablevalue = (DataEncoder.IResolvableValue)decode(is, DataEncoder.EncodedType.World); -- final BlockPos blockpos = (BlockPos)decode(is, DataEncoder.EncodedType.BlockPos); -- return new DataEncoder.IResolvableValue() { -- public TileEntity get() { -- World world = iresolvablevalue.get(); -- return world == null ? null : world.getTileEntity(blockpos); -- } -- }; -- case TupleT2: -- return new Tuple.T2(decode(is), decode(is)); -- case TupleT3: -- return new Tuple.T3(decode(is), decode(is), decode(is)); -- case UUID: -- return new UUID(is.readLong(), is.readLong()); -- case Vec3: -- return new Vec3d(is.readDouble(), is.readDouble(), is.readDouble()); -- case World: -- final int i = is.readInt(); -- return new DataEncoder.IResolvableValue() { -- public World get() { -- return IC2.platform.getWorld(i); -- } -- }; -- default: -- throw new IllegalArgumentException("unhandled type: " + type); -+ for (int i = 0; i < len; ++i) { -+ EncodedType cType = DataEncoder.typeFromId(is.readUnsignedByte()); -+ if (!cType.threadSafe && !needsResolving) { -+ needsResolving = true; -+ if (componentClass != Object.class) { -+ Object[] newArray = new Object[len]; -+ System.arraycopy(array, 0, newArray, 0, i); -+ array = newArray; -+ } -+ } -+ Array.set(array, i, DataEncoder.decode(is, cType)); -+ } -+ } -+ if (!needsResolving) { -+ return array; ++ return decode(is, DataEncoder.EncodedType.NBTTagCompound); + case CropCard: + return Crops.instance.getCropCard(is.readString(), is.readString()); + case Double: +@@ -587,40 +588,38 @@ + } else { + return false; + } ++ } else if (dst instanceof FluidTank) { ++ FluidTank fluidtank = (FluidTank)src; ++ FluidTank fluidtank1 = (FluidTank)dst; ++ fluidtank1.setFluid(fluidtank.getFluid()); ++ fluidtank1.setCapacity(fluidtank.getCapacity()); ++ } else if (dst instanceof InvSlot) { ++ InvSlot invslot = (InvSlot)src; ++ InvSlot invslot1 = (InvSlot)dst; ++ if (invslot.size() != invslot1.size()) { ++ throw new RuntimeException("Can't sync InvSlots with mismatched sizes."); + } -+ final Object tmpArray = array; -+ return new IResolvableValue(){ + -+ @Override -+ public Object get() { -+ Object ret = Array.newInstance(componentClass, len); -+ for (int i = 0; i < len; ++i) { -+ Array.set(ret, i, DataEncoder.getValue(Array.get(tmpArray, i))); -+ } -+ return ret; ++ for(int i = 0; i < invslot.size(); ++i) { ++ if (!copyValue(invslot.get(i), invslot1.get(i))) { ++ invslot1.put(i, invslot.get(i)); + } -+ }; -+ } -+ case Block: { -+ return Util.getBlock((ResourceLocation)DataEncoder.decode(is, EncodedType.ResourceLocation)); -+ } -+ case BlockPos: { -+ return new BlockPos(is.readInt(), is.readInt(), is.readInt()); -+ } -+ case Boolean: { -+ return is.readBoolean(); -+ } -+ case Byte: { -+ return is.readByte(); -+ } -+ case Character: { -+ return Character.valueOf(is.readChar()); -+ } -+ case ChunkPos: { -+ return new ChunkPos(is.readInt(), is.readInt()); -+ } -+ case Collection: { -+ final Object ret = DataEncoder.decode(is, EncodedType.Array); -+ if (ret instanceof IResolvableValue) { -+ return new IResolvableValue>(){ -+ -+ @Override -+ public List get() { -+ return Arrays.asList((Object[])((IResolvableValue)ret).get()); -+ } -+ }; -+ } -+ return Arrays.asList((Object[])ret); -+ } -+ case Component: { -+ return DataEncoder.decode(is, EncodedType.NBTTagCompound); -+ } -+ case CropCard: { -+ return Crops.instance.getCropCard(is.readString(), is.readString()); -+ } -+ case Double: { -+ return is.readDouble(); -+ } -+ case ElectrolyzerRecipe: { -+ int inputAmount = is.readInt(); -+ int EUaTick = is.readInt(); -+ int ticksNeeded = is.readInt(); -+ byte max = is.readByte(); -+ IElectrolyzerRecipeManager.ElectrolyzerOutput[] outputs = new IElectrolyzerRecipeManager.ElectrolyzerOutput[max]; -+ for (byte i = 0; i < max; i = (byte)(i + 1)) { -+ outputs[i] = new IElectrolyzerRecipeManager.ElectrolyzerOutput(is.readString(), is.readInt(), EnumFacing.getFront((int)is.readByte())); -+ } -+ return new IElectrolyzerRecipeManager.ElectrolyzerRecipe(inputAmount, EUaTick, ticksNeeded, outputs); -+ } -+ case Enchantment: { -+ return Enchantment.REGISTRY.getObject(((ResourceLocation)DataEncoder.decode(is, EncodedType.ResourceLocation))); -+ } -+ case Enum: { -+ return is.readVarInt(); -+ } -+ case Float: { -+ return Float.valueOf(is.readFloat()); -+ } -+ case Fluid: { -+ return FluidRegistry.getFluid((String)is.readString()); -+ } -+ case FluidStack: { -+ FluidStack ret = new FluidStack((Fluid)DataEncoder.decode(is, EncodedType.Fluid), is.readInt()); -+ ret.tag = (NBTTagCompound)DataEncoder.decode(is); -+ return ret; -+ } -+ case FluidTank: { -+ return new FluidTank((FluidStack)DataEncoder.decode(is), is.readInt()); -+ } -+ case GameProfile: { -+ return new GameProfile((UUID)DataEncoder.decode(is), is.readString()); -+ } -+ case Integer: { -+ return is.readInt(); -+ } -+ case InvSlot: { -+ ItemStack[] contents = (ItemStack[])DataEncoder.decode(is, EncodedType.Array); -+ InvSlot ret = new InvSlot(contents.length); -+ for (int i = 0; i < contents.length; ++i) { -+ ret.put(i, contents[i]); + } -+ return ret; -+ } -+ case Item: { -+ return Util.getItem((ResourceLocation)DataEncoder.decode(is, EncodedType.ResourceLocation)); -+ } -+ case ItemStack: { -+ byte size = is.readByte(); -+ if (size == 0) { -+ return StackUtil.emptyStack; -+ } -+ Item item = DataEncoder.decode(is, Item.class); -+ short meta = is.readShort(); -+ NBTTagCompound nbt = (NBTTagCompound)DataEncoder.decode(is); -+ ItemStack ret = new ItemStack(item, (int)size, (int)meta); -+ ret.setTagCompound(nbt); -+ return ret; -+ } -+ case Long: { -+ return is.readLong(); -+ } -+ case NBTTagCompound: { -+ return CompressedStreamTools.read((DataInput)is, (NBTSizeTracker)NBTSizeTracker.INFINITE); -+ } -+ case Null: { -+ return null; -+ } -+ case Object: { -+ return new Object(); -+ } -+ case Potion: { -+ return Potion.REGISTRY.getObject(((ResourceLocation)DataEncoder.decode(is, EncodedType.ResourceLocation))); -+ } -+ case ResourceLocation: { -+ return new ResourceLocation(is.readString(), is.readString()); -+ } -+ case Short: { -+ return is.readShort(); -+ } -+ case String: { -+ return is.readString(); -+ } -+ case TileEntity: { -+ final IResolvableValue deferredWorld = (IResolvableValue)DataEncoder.decode(is, EncodedType.World); -+ final BlockPos pos = (BlockPos)DataEncoder.decode(is, EncodedType.BlockPos); -+ return new IResolvableValue(){ -+ -+ @Override -+ public TileEntity get() { -+ World world = (World)deferredWorld.get(); -+ if (world == null) { -+ return null; -+ } -+ return world.getTileEntity(pos); -+ } -+ }; -+ } -+ case TupleT2: { -+ return new Tuple.T2(DataEncoder.decode(is), DataEncoder.decode(is)); -+ } -+ case TupleT3: { -+ return new Tuple.T3(DataEncoder.decode(is), DataEncoder.decode(is), DataEncoder.decode(is)); -+ } -+ case UUID: { -+ return new UUID(is.readLong(), is.readLong()); -+ } -+ case Vec3: { -+ return new Vec3d(is.readDouble(), is.readDouble(), is.readDouble()); -+ } -+ case World: { -+ final int dimensionId = is.readInt(); -+ return new IResolvableValue(){ -+ -+ @Override -+ public World get() { -+ return IC2.platform.getWorld(dimensionId); -+ } -+ }; -+ } - } -+ throw new IllegalArgumentException("unhandled type: " + (Object)((Object)type)); - } - - public static T getValue(Object decoded) { -- return (T)(decoded instanceof DataEncoder.IResolvableValue ? ((DataEncoder.IResolvableValue)decoded).get() : decoded); -+ if (decoded instanceof IResolvableValue) { -+ return (T) ((IResolvableValue)decoded).get(); -+ } -+ return (T)decoded; - } - - public static boolean copyValue(T src, T dst) { -- if (src != null && dst != null) { -- if (dst instanceof ItemStack) { -- ItemStack itemstack = (ItemStack)src; -- ItemStack itemstack1 = (ItemStack)dst; -- if (itemstack.getItem() == itemstack1.getItem()) { -- itemstack1.setCount(itemstack.getCount()); -- StackUtil.setRawMeta(itemstack1, StackUtil.getRawMeta(itemstack)); -- itemstack1.setTagCompound(itemstack.getTagCompound()); -- return true; -- } else { -- return false; -- } -- } else { ++ } else if (dst instanceof TileEntityComponent) { ++ NBTTagCompound nbttagcompound = (NBTTagCompound)src; ++ ((TileEntityComponent)dst).readFromNbt(nbttagcompound); + } else { - if (dst instanceof FluidTank) { - FluidTank fluidtank = (FluidTank)src; - FluidTank fluidtank1 = (FluidTank)dst; @@ -1125,297 +87,18 @@ - Collection collection1 = (Collection)dst; - collection1.clear(); - collection1.addAll(collection); -- } -- -+ if (src == null || dst == null) { -+ return false; -+ } -+ if (dst instanceof ItemStack) { -+ ItemStack srcT = (ItemStack)src; -+ ItemStack dstT = (ItemStack)dst; -+ if (srcT.getItem() == dstT.getItem()) { -+ dstT.setCount(srcT.getCount()); -+ StackUtil.setRawMeta(dstT, StackUtil.getRawMeta(srcT)); -+ dstT.setTagCompound(srcT.getTagCompound()); - return true; ++ if (!(dst instanceof Collection)) { ++ return false; + } + +- return true; ++ Collection collection = (Collection)src; ++ Collection collection1 = (Collection)dst; ++ collection1.clear(); ++ collection1.addAll(collection); } -+ return false; -+ } -+ if (dst instanceof FluidTank) { -+ FluidTank srcT = (FluidTank)src; -+ FluidTank dstT = (FluidTank)dst; -+ dstT.setFluid(srcT.getFluid()); -+ dstT.setCapacity(srcT.getCapacity()); -+ } else if (dst instanceof InvSlot) { -+ InvSlot srcT = (InvSlot)src; -+ InvSlot dstT = (InvSlot)dst; -+ if (srcT.size() != dstT.size()) { -+ throw new RuntimeException("Can't sync InvSlots with mismatched sizes."); -+ } -+ for (int i = 0; i < srcT.size(); ++i) { -+ if (DataEncoder.copyValue(srcT.get(i), dstT.get(i))) continue; -+ dstT.put(i, srcT.get(i)); -+ } -+ } else if (dst instanceof TileEntityComponent) { -+ NBTTagCompound nbt = (NBTTagCompound)src; -+ ((TileEntityComponent)dst).readFromNbt(nbt); -+ } else if (dst instanceof Collection) { -+ Collection srcT = (Collection)src; -+ Collection dstT = (Collection)dst; -+ dstT.clear(); -+ dstT.addAll(srcT); ++ ++ return true; } else { return false; } -+ return true; - } - - private static Class box(Class clazz) { - if (clazz == Byte.TYPE) { - return Byte.class; -- } else if (clazz == Short.TYPE) { -+ } -+ if (clazz == Short.TYPE) { - return Short.class; -- } else if (clazz == Integer.TYPE) { -+ } -+ if (clazz == Integer.TYPE) { - return Integer.class; -- } else if (clazz == Long.TYPE) { -+ } -+ if (clazz == Long.TYPE) { - return Long.class; -- } else if (clazz == Float.TYPE) { -+ } -+ if (clazz == Float.TYPE) { - return Float.class; -- } else if (clazz == Double.TYPE) { -+ } -+ if (clazz == Double.TYPE) { - return Double.class; -- } else if (clazz == Boolean.TYPE) { -+ } -+ if (clazz == Boolean.TYPE) { - return Boolean.class; -- } else { -- return clazz == Character.TYPE ? Character.class : clazz; -- } -+ } -+ if (clazz == Character.TYPE) { -+ return Character.class; -+ } -+ return clazz; - } - - private static Class unbox(Class clazz) { - if (clazz == Byte.class) { - return Byte.TYPE; -- } else if (clazz == Short.class) { -+ } -+ if (clazz == Short.class) { - return Short.TYPE; -- } else if (clazz == Integer.class) { -+ } -+ if (clazz == Integer.class) { - return Integer.TYPE; -- } else if (clazz == Long.class) { -+ } -+ if (clazz == Long.class) { - return Long.TYPE; -- } else if (clazz == Float.class) { -+ } -+ if (clazz == Float.class) { - return Float.TYPE; -- } else if (clazz == Double.class) { -+ } -+ if (clazz == Double.class) { - return Double.TYPE; -- } else if (clazz == Boolean.class) { -+ } -+ if (clazz == Boolean.class) { - return Boolean.TYPE; -- } else { -- return clazz == Character.class ? Character.TYPE : clazz; -- } -+ } -+ if (clazz == Character.class) { -+ return Character.TYPE; -+ } -+ return clazz; - } - - private static Class getClass(String type) { - try { - return Class.forName(type); -- } catch (ClassNotFoundException classnotfoundexception) { -- throw new RuntimeException("Missing type from the class path expected by network: " + type, classnotfoundexception); -+ } -+ catch (ClassNotFoundException e) { -+ throw new RuntimeException("Missing type from the class path expected by network: " + type, e); - } - } - -- private static int idFromType(DataEncoder.EncodedType type) { -+ private static int idFromType(EncodedType type) { - return type.ordinal(); - } - -- private static DataEncoder.EncodedType typeFromId(int id) { -- if (id >= 0 && id < DataEncoder.EncodedType.types.length) { -- return DataEncoder.EncodedType.types[id]; -- } else { -+ private static EncodedType typeFromId(int id) { -+ if (id < 0 || id >= EncodedType.types.length) { - throw new IllegalArgumentException("invalid type id: " + id); - } -- } -- -- private static DataEncoder.EncodedType typeFromObject(Object o) { -- return o == null ? DataEncoder.EncodedType.Null : typeFromClass(o.getClass()); -- } -- -- private static DataEncoder.EncodedType typeFromClass(Class cls) { -+ return EncodedType.types[id]; -+ } -+ -+ private static EncodedType typeFromObject(Object o) { -+ if (o == null) { -+ return EncodedType.Null; -+ } -+ return DataEncoder.typeFromClass(o.getClass()); -+ } -+ -+ private static EncodedType typeFromClass(Class cls) { -+ EncodedType ret; - if (cls == null) { -- return DataEncoder.EncodedType.Null; -- } else if (cls.isArray()) { -- return DataEncoder.EncodedType.Array; -- } else { -- if (cls.isPrimitive()) { -- cls = box(cls); -- } -- -- DataEncoder.EncodedType dataencoder$encodedtype = DataEncoder.EncodedType.classToTypeMap.get(cls); -- if (dataencoder$encodedtype != null) { -- return dataencoder$encodedtype; -- } else { -- dataencoder$encodedtype = classToTypeCache.get(cls); -- if (dataencoder$encodedtype != null) { -- return dataencoder$encodedtype; -- } else { -- INetworkCustomEncoder inetworkcustomencoder = classToAddonType.get(cls); -- if (inetworkcustomencoder != null) { -- dataencoder$encodedtype = inetworkcustomencoder.isThreadSafe() ? DataEncoder.EncodedType.Addon : DataEncoder.EncodedType.UnSafeAddon; -- classToTypeCache.put(cls, dataencoder$encodedtype); -- return dataencoder$encodedtype; -- } else { -- for(DataEncoder.EncodedType dataencoder$encodedtype1 : DataEncoder.EncodedType.types) { -- if (dataencoder$encodedtype1.cls != null && dataencoder$encodedtype1.cls.isAssignableFrom(cls)) { -- classToTypeCache.put(cls, dataencoder$encodedtype1); -- return dataencoder$encodedtype1; -- } -- } -- -- throw new IllegalStateException("unmatched " + cls); -- } -- } -- } -- } -+ return EncodedType.Null; -+ } -+ if (cls.isArray()) { -+ return EncodedType.Array; -+ } -+ if (cls.isPrimitive()) { -+ cls = DataEncoder.box(cls); -+ } -+ if ((ret = EncodedType.classToTypeMap.get(cls)) != null) { -+ return ret; -+ } -+ ret = classToTypeCache.get(cls); -+ if (ret != null) { -+ return ret; -+ } -+ INetworkCustomEncoder ince = classToAddonType.get(cls); -+ if (ince != null) { -+ ret = ince.isThreadSafe() ? EncodedType.Addon : EncodedType.UnSafeAddon; -+ classToTypeCache.put(cls, ret); -+ return ret; -+ } -+ for (EncodedType type : EncodedType.types) { -+ if (type.cls == null || !type.cls.isAssignableFrom(cls)) continue; -+ classToTypeCache.put(cls, type); -+ return type; -+ } -+ throw new IllegalStateException("unmatched " + cls); - } - - public static void addNetworkEncoder(Class typeBeingEncoded, INetworkCustomEncoder customEncoder) { -- assert typeBeingEncoded != null && customEncoder != null; -- -- INetworkCustomEncoder inetworkcustomencoder = classToAddonType.put(typeBeingEncoded, customEncoder); -- if (inetworkcustomencoder != null) { -- throw new IllegalStateException("Duplicate mapping for class! " + inetworkcustomencoder.getClass().getName() + " and " + customEncoder.getClass().getName() + " both map for " + typeBeingEncoded.getName() + '.'); -+ assert (typeBeingEncoded != null && customEncoder != null); -+ INetworkCustomEncoder previous = classToAddonType.put(typeBeingEncoded, customEncoder); -+ if (previous != null) { -+ throw new IllegalStateException("Duplicate mapping for class! " + previous.getClass().getName() + " and " + customEncoder.getClass().getName() + " both map for " + typeBeingEncoded.getName() + '.'); - } - } - - public static enum EncodedType { -- Null((Class)null), -- Array((Class)null), -+ Null(null), -+ Array(null), - Byte(Byte.class), - Short(Short.class), - Integer(Integer.class), -@@ -773,15 +832,15 @@ - ElectrolyzerRecipe(IElectrolyzerRecipeManager.ElectrolyzerRecipe.class), - TupleT2(Tuple.T2.class), - TupleT3(Tuple.T3.class), -- Addon((Class)null), -- UnSafeAddon((Class)null, false), -+ Addon(null), -+ UnSafeAddon(null, false), - Collection(Collection.class), - Object(Object.class); - - final Class cls; - final boolean threadSafe; -- static final DataEncoder.EncodedType[] types = values(); -- static final Map, DataEncoder.EncodedType> classToTypeMap = new IdentityHashMap, DataEncoder.EncodedType>(types.length - 2); -+ static final EncodedType[] types; -+ static final Map, EncodedType> classToTypeMap; - - private EncodedType(Class cls) { - this(cls, true); -@@ -793,19 +852,19 @@ - } - - static { -- for(DataEncoder.EncodedType dataencoder$encodedtype : types) { -- if (dataencoder$encodedtype.cls != null) { -- classToTypeMap.put(dataencoder$encodedtype.cls, dataencoder$encodedtype); -- } -+ types = EncodedType.values(); -+ classToTypeMap = new IdentityHashMap(types.length - 2); -+ for (EncodedType type : types) { -+ if (type.cls == null) continue; -+ classToTypeMap.put(type.cls, type); - } -- - if (types.length > 255) { - throw new RuntimeException("too many types"); - } - } - } - -- private interface IResolvableValue { -- T get(); -+ private static interface IResolvableValue { -+ public T get(); - } - } diff --git a/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/network/GrowingBuffer.java.patch b/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/network/GrowingBuffer.java.patch index a816a47..bd6c69d 100644 --- a/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/network/GrowingBuffer.java.patch +++ b/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/core/network/GrowingBuffer.java.patch @@ -1,11 +1,26 @@ --- a/ic2/core/network/GrowingBuffer.java +++ b/ic2/core/network/GrowingBuffer.java -@@ -214,7 +214,7 @@ +@@ -213,18 +213,15 @@ + if (i < 0) { throw new IllegalArgumentException("only positive numbers are supported"); } else { - while(true) { +- while(true) { - int i = i & 127; -+ i = i & 127; ++ do { ++ int part = i & 127; i >>>= 7; if (i != 0) { - i |= 128; +- i |= 128; ++ part |= 128; + } + +- this.writeByte(i); +- if (i == 0) { +- break; +- } +- } ++ this.writeByte(part); ++ } while(i != 0); + + } + } diff --git a/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/jeiIntegration/transferhandlers/TransferHandlerBatchCrafter.java.patch b/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/jeiIntegration/transferhandlers/TransferHandlerBatchCrafter.java.patch new file mode 100644 index 0000000..2bb6ffe --- /dev/null +++ b/projects/IC2-Base/patches[2.8.164,2.8.165]/minecraft/ic2/jeiIntegration/transferhandlers/TransferHandlerBatchCrafter.java.patch @@ -0,0 +1,45 @@ +--- a/ic2/jeiIntegration/transferhandlers/TransferHandlerBatchCrafter.java ++++ b/ic2/jeiIntegration/transferhandlers/TransferHandlerBatchCrafter.java +@@ -2,8 +2,6 @@ + + import ic2.core.IC2; + import ic2.core.block.machine.container.ContainerBatchCrafter; +-import ic2.core.block.machine.tileentity.TileEntityBatchCrafter; +-import ic2.core.network.NetworkManager; + import ic2.core.util.StackUtil; + import java.util.Map; + import mezz.jei.api.gui.IGuiIngredient; +@@ -13,7 +11,6 @@ + import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; + import net.minecraft.entity.player.EntityPlayer; + import net.minecraft.item.ItemStack; +-import net.minecraft.tileentity.TileEntity; + + public class TransferHandlerBatchCrafter implements IRecipeTransferHandler { + public Class getContainerClass() { +@@ -28,19 +25,19 @@ + Map> map = iguiitemstackgroup.getGuiIngredients(); + + for(int i = 0; i < 9; ++i) { +- IGuiIngredient iguiingredient = (IGuiIngredient)map.get(Integer.valueOf(i + 1)); ++ IGuiIngredient iguiingredient = map.get(i + 1); + ItemStack itemstack; + if (iguiingredient != null) { +- itemstack = (ItemStack)iguiingredient.getDisplayedIngredient(); ++ itemstack = iguiingredient.getDisplayedIngredient(); + } else { + itemstack = StackUtil.emptyStack; + } + +- ((TileEntityBatchCrafter)container.base).craftingGrid[i] = itemstack; ++ container.base.craftingGrid[i] = itemstack; + } +- +- ((NetworkManager)IC2.network.get(false)).updateTileEntityField((TileEntity)container.base, "craftingGrid"); +- ((NetworkManager)IC2.network.get(false)).initiateClientTileEntityEvent((TileEntity)container.base, 0); ++ ++ IC2.network.get(false).updateTileEntityField(container.base, "craftingGrid"); ++ IC2.network.get(false).initiateClientTileEntityEvent(container.base, 0); + return null; + } + } diff --git a/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch b/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch new file mode 100644 index 0000000..d84d71f --- /dev/null +++ b/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch @@ -0,0 +1,44 @@ +--- a/ic2/core/block/machine/container/ContainerBatchCrafter.java ++++ b/ic2/core/block/machine/container/ContainerBatchCrafter.java +@@ -12,7 +12,6 @@ + import java.util.Collections; + import java.util.List; + import net.minecraft.entity.player.EntityPlayer; +-import net.minecraft.inventory.Slot; + import net.minecraft.item.ItemStack; + + public class ContainerBatchCrafter extends ContainerElectricMachine { +@@ -26,10 +25,9 @@ + for(int j = 0; j < 3; ++j) { + this.addSlotToContainer(new SlotHologramSlot(tileEntity.craftingGrid, j + i * 3, 30 + j * 18, 17 + i * 18, 1, new SlotHologramSlot.ChangeCallback() { + public void onChanged(int index) { +- if (((TileEntityBatchCrafter)ContainerBatchCrafter.this.base).hasWorld() && !((TileEntityBatchCrafter)ContainerBatchCrafter.this.base).getWorld().isRemote) { +- ((TileEntityBatchCrafter)ContainerBatchCrafter.this.base).matrixChange(index); ++ if (ContainerBatchCrafter.this.base.hasWorld() && !ContainerBatchCrafter.this.base.getWorld().isRemote) { ++ ContainerBatchCrafter.this.base.matrixChange(index); + } +- + } + })); + } +@@ -49,15 +47,15 @@ + } + + protected ItemStack handlePlayerSlotShiftClick(EntityPlayer player, ItemStack sourceItemStack) { +- Tuple.T2, ? extends TIntCollection> t2 = StackUtil.balanceStacks(((TileEntityBatchCrafter)this.base).ingredients, ((TileEntityBatchCrafter)this.base).acceptPredicate, StackUtil.getSlotsFromInv(((TileEntityBatchCrafter)this.base).ingredients), Collections.singleton(sourceItemStack)); +- TIntIterator tintiterator = ((TIntCollection)t2.b).iterator(); ++ Tuple.T2, ? extends TIntCollection> t2 = StackUtil.balanceStacks(this.base.ingredients, this.base.acceptPredicate, StackUtil.getSlotsFromInv(this.base.ingredients), Collections.singleton(sourceItemStack)); ++ TIntIterator tintiterator = t2.b.iterator(); + +- while(tintiterator.hasNext()) { ++ while (tintiterator.hasNext()) { + int i = tintiterator.next(); +- ((Slot)this.inventorySlots.get(this.indexToSlot.get(i))).onSlotChanged(); ++ this.inventorySlots.get(this.indexToSlot.get(i)).onSlotChanged(); + } + +- sourceItemStack = ((List)t2.a).isEmpty() ? StackUtil.emptyStack : (ItemStack)((List)t2.a).get(0); ++ sourceItemStack = t2.a.isEmpty() ? StackUtil.emptyStack : t2.a.get(0); + return sourceItemStack; + } + diff --git a/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch b/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch index 9d8e96d..5af1efa 100644 --- a/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch +++ b/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch @@ -1,5 +1,14 @@ --- a/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java +++ b/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java +@@ -122,7 +122,7 @@ + }; + this.acceptPredicate = new Predicate>() { + public boolean apply(Tuple.T2 input) { +- return TileEntityBatchCrafter.this.ingredientsRow[((Integer)input.b).intValue()].accepts((ItemStack)input.a); ++ return TileEntityBatchCrafter.this.ingredientsRow[input.b].accepts(input.a); + } + }; + this.recipe = null; @@ -133,8 +133,9 @@ this.progress = 0; this.guiProgress = 0.0F; diff --git a/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/network/DataEncoder.java.patch b/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/network/DataEncoder.java.patch index f55f95a..a44dc40 100644 --- a/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/network/DataEncoder.java.patch +++ b/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/network/DataEncoder.java.patch @@ -1,1101 +1,63 @@ --- a/ic2/core/network/DataEncoder.java +++ b/ic2/core/network/DataEncoder.java -@@ -9,9 +9,12 @@ - import ic2.core.IC2; - import ic2.core.block.comp.TileEntityComponent; - import ic2.core.block.invslot.InvSlot; -+import ic2.core.network.GrowingBuffer; - import ic2.core.util.StackUtil; - import ic2.core.util.Tuple; - import ic2.core.util.Util; -+import java.io.DataInput; -+import java.io.DataOutput; - import java.io.IOException; - import java.lang.reflect.Array; - import java.util.Arrays; -@@ -42,704 +45,760 @@ - import net.minecraftforge.fluids.FluidTank; - - public final class DataEncoder { -- private static final Map, DataEncoder.EncodedType> classToTypeCache = Collections., DataEncoder.EncodedType>synchronizedMap(new IdentityHashMap()); -- private static final Map, INetworkCustomEncoder> classToAddonType = Collections., INetworkCustomEncoder>synchronizedMap(new IdentityHashMap()); -+ private static final Map, EncodedType> classToTypeCache = Collections.synchronizedMap(new IdentityHashMap()); -+ private static final Map, INetworkCustomEncoder> classToAddonType = Collections.synchronizedMap(new IdentityHashMap()); - - public static void encode(GrowingBuffer os, Object o) throws IOException { - try { -- encode(os, o, true); -- } catch (IllegalArgumentException illegalargumentexception) { -- IC2.platform.displayError(illegalargumentexception, "An unknown data type was attempted to be encoded for sending through\nmultiplayer.\nThis could happen due to a bug."); -- } -- -+ DataEncoder.encode(os, o, true); -+ } -+ catch (IllegalArgumentException e) { -+ IC2.platform.displayError(e, "An unknown data type was attempted to be encoded for sending through\nmultiplayer.\nThis could happen due to a bug.", new Object[0]); -+ } - } - - public static void encode(IGrowingBuffer os, Object o, boolean withType) throws IOException { -- DataEncoder.EncodedType dataencoder$encodedtype = typeFromObject(o); -+ EncodedType type = DataEncoder.typeFromObject(o); - if (withType) { -- os.writeByte(idFromType(dataencoder$encodedtype)); -+ os.writeByte(DataEncoder.idFromType(type)); - } -- -- switch(dataencoder$encodedtype) { -- case Addon: -- case UnSafeAddon: -- assert o != null; -- -- INetworkCustomEncoder inetworkcustomencoder = classToAddonType.get(o.getClass()); -- if (inetworkcustomencoder == null) { -- throw new IllegalStateException("Cannot encode an object without an encoder! Type was " + o.getClass()); -+ return; -+ /*switch (type) { -+ case Addon: -+ case UnSafeAddon: { -+ assert (o != null); -+ INetworkCustomEncoder ince = classToAddonType.get(o.getClass()); -+ if (ince == null) { -+ throw new IllegalStateException("Cannot encode an object without an encoder! Type was " + o.getClass()); -+ } -+ os.writeString(o.getClass().getName()); -+ ince.encode(os, o); -+ break; - } -- -- os.writeString(o.getClass().getName()); -- inetworkcustomencoder.encode(os, o); -- break; -- case Array: -- Class oclass = o.getClass().getComponentType(); -- int j = Array.getLength(o); -- if (oclass == Object.class && j > 0) { -- boolean flag = false; -- Class oclass1 = null; -- -- label203: -- for(int k = 0; k < j; ++k) { -- Object object = Array.get(o, k); -- if (oclass1 == null) { -- if (object instanceof Enum) { -- oclass1 = ((Enum)object).getDeclaringClass(); -- flag = true; -- } else if (object != null) { -- oclass1 = object.getClass(); -- -- assert oclass1 != Object.class; -+ case Array: { -+ Object value; -+ int i; -+ Class componentClass = o.getClass().getComponentType(); -+ int len = Array.getLength(o); -+ if (componentClass == Object.class && len > 0) { -+ boolean isEnum = false; -+ Class target = null; -+ block40: for (i = 0; i < len; ++i) { -+ value = Array.get(o, i); -+ if (target == null) { -+ if (value instanceof Enum) { -+ target = ((Enum)value).getDeclaringClass(); -+ isEnum = true; -+ continue; -+ } -+ if (value == null) continue; -+ target = value.getClass(); -+ assert (target != Object.class); -+ continue; - } -- } else if (object != null) { -- Class oclass2 = object.getClass(); -- if (oclass2 != oclass1 && !oclass1.isAssignableFrom(oclass2)) { -- if (flag || object instanceof Enum) { -- throw new IllegalArgumentException("Array of mixed enum entries"); -- } -- -- while((oclass1 = oclass1.getSuperclass()) != Object.class) { -- if (oclass1.isAssignableFrom(oclass2)) { -- continue label203; -- } -- } -- -- ++k; -- -- while(k < j) { -- if (Array.get(o, k) instanceof Enum) { -+ if (value != null) { -+ Class valueClass = value.getClass(); -+ if (valueClass != target && !target.isAssignableFrom(valueClass)) { -+ if (isEnum || value instanceof Enum) { - throw new IllegalArgumentException("Array of mixed enum entries"); - } -- -- ++k; -+ while ((target = target.getSuperclass()) != Object.class) { -+ if (!target.isAssignableFrom(valueClass)) continue; -+ continue block40; -+ } -+ ++i; -+ while (i < len) { -+ if (Array.get(o, i) instanceof Enum) { -+ throw new IllegalArgumentException("Array of mixed enum entries"); -+ } -+ ++i; -+ } -+ target = Object.class; -+ break; - } -- -- oclass1 = Object.class; -- break; -- } else { -- assert flag == (object instanceof Enum); -+ assert (isEnum == value instanceof Enum); -+ continue; - } -- } else if (flag) { -+ if (!isEnum) continue; - throw new IllegalArgumentException("Enum array with null entry"); - } -- } -- -- oclass = oclass1; -- } -- -- DataEncoder.EncodedType dataencoder$encodedtype1 = typeFromClass(oclass); -- os.writeByte(idFromType(dataencoder$encodedtype1)); -- os.writeBoolean(oclass.isPrimitive()); -- if (dataencoder$encodedtype1 == DataEncoder.EncodedType.Addon || dataencoder$encodedtype1 == DataEncoder.EncodedType.UnSafeAddon || dataencoder$encodedtype1 == DataEncoder.EncodedType.Enum) { -- os.writeString(oclass.getName()); -- } -- -- os.writeVarInt(j); -- boolean flag1 = false; -- -- for(int l = 0; l < j; ++l) { -- Object object1 = Array.get(o, l); -- if (object1 == null || typeFromClass(object1.getClass()) != dataencoder$encodedtype1) { -- flag1 = true; -- break; -- } -- } -- -- os.writeBoolean(flag1); -- -- for(int i1 = 0; i1 < j; ++i1) { -- encode(os, Array.get(o, i1), flag1); -- } -- break; -- case Block: -- encode(os, Util.getName((Block)o), false); -- break; -- case BlockPos: -- BlockPos blockpos = (BlockPos)o; -- os.writeInt(blockpos.getX()); -- os.writeInt(blockpos.getY()); -- os.writeInt(blockpos.getZ()); -- break; -- case Boolean: -- os.writeBoolean(((Boolean)o).booleanValue()); -- break; -- case Byte: -- os.writeByte(((Byte)o).byteValue()); -- break; -- case Character: -- os.writeChar(((Character)o).charValue()); -- break; -- case ChunkPos: -- ChunkPos chunkpos = (ChunkPos)o; -- os.writeInt(chunkpos.x); -- os.writeInt(chunkpos.z); -- break; -- case Collection: -- encode(os, ((Collection)o).toArray(), false); -- break; -- case Component: -- NBTTagCompound nbttagcompound = ((TileEntityComponent)o).writeToNbt(); -- encode(os, nbttagcompound == null ? new NBTTagCompound() : nbttagcompound, false); -- break; -- case CropCard: -- CropCard cropcard = (CropCard)o; -- os.writeString(cropcard.getOwner()); -- os.writeString(cropcard.getId()); -- break; -- case Double: -- os.writeDouble(((Double)o).doubleValue()); -- break; -- case ElectrolyzerRecipe: -- IElectrolyzerRecipeManager.ElectrolyzerRecipe ielectrolyzerrecipemanager$electrolyzerrecipe = (IElectrolyzerRecipeManager.ElectrolyzerRecipe)o; -- os.writeInt(ielectrolyzerrecipemanager$electrolyzerrecipe.inputAmount); -- os.writeInt(ielectrolyzerrecipemanager$electrolyzerrecipe.EUaTick); -- os.writeInt(ielectrolyzerrecipemanager$electrolyzerrecipe.ticksNeeded); -- IElectrolyzerRecipeManager.ElectrolyzerOutput[] aielectrolyzerrecipemanager$electrolyzeroutput = ielectrolyzerrecipemanager$electrolyzerrecipe.outputs; -- os.writeByte(aielectrolyzerrecipemanager$electrolyzeroutput.length); -- -- for(IElectrolyzerRecipeManager.ElectrolyzerOutput ielectrolyzerrecipemanager$electrolyzeroutput : aielectrolyzerrecipemanager$electrolyzeroutput) { -- os.writeString(ielectrolyzerrecipemanager$electrolyzeroutput.fluidName); -- os.writeInt(ielectrolyzerrecipemanager$electrolyzeroutput.fluidAmount); -- os.writeByte(ielectrolyzerrecipemanager$electrolyzeroutput.tankDirection.getIndex()); -- } -- -- return; -- case Enchantment: -- encode(os, Enchantment.REGISTRY.getNameForObject((Enchantment)o), false); -- break; -- case Enum: -- os.writeVarInt(((Enum)o).ordinal()); -- break; -- case Float: -- os.writeFloat(((Float)o).floatValue()); -- break; -- case Fluid: -- os.writeString(((Fluid)o).getName()); -- break; -- case FluidStack: -- FluidStack fluidstack = (FluidStack)o; -- encode(os, fluidstack.getFluid(), false); -- os.writeInt(fluidstack.amount); -- encode(os, fluidstack.tag, true); -- break; -- case FluidTank: -- FluidTank fluidtank = (FluidTank)o; -- encode(os, fluidtank.getFluid(), true); -- os.writeInt(fluidtank.getCapacity()); -- break; -- case GameProfile: -- GameProfile gameprofile = (GameProfile)o; -- encode(os, gameprofile.getId(), true); -- os.writeString(gameprofile.getName()); -- break; -- case Integer: -- os.writeInt(((Integer)o).intValue()); -- break; -- case InvSlot: -- InvSlot invslot = (InvSlot)o; -- ItemStack[] aitemstack = new ItemStack[invslot.size()]; -- -- for(int i = 0; i < invslot.size(); ++i) { -- aitemstack[i] = invslot.get(i); -- } -- -- encode(os, aitemstack, false); -- break; -- case Item: -- encode(os, Util.getName((Item)o), false); -- break; -- case ItemStack: -- ItemStack itemstack = (ItemStack)o; -- if (StackUtil.isEmpty(itemstack)) { -- os.writeByte(0); -- } else { -- os.writeByte(StackUtil.getSize(itemstack)); -- encode(os, itemstack.getItem(), false); -- os.writeShort(itemstack.getItemDamage()); -- encode(os, itemstack.getTagCompound(), true); -- } -- break; -- case Long: -- os.writeLong(((Long)o).longValue()); -- break; -- case NBTTagCompound: -- CompressedStreamTools.write((NBTTagCompound)o, os); -- break; -- case Null: -- if (!withType) { -+ componentClass = target; -+ } -+ EncodedType componentType = DataEncoder.typeFromClass(componentClass); -+ os.writeByte(DataEncoder.idFromType(componentType)); -+ os.writeBoolean(componentClass.isPrimitive()); -+ if (componentType == EncodedType.Addon || componentType == EncodedType.UnSafeAddon || componentType == EncodedType.Enum) { -+ os.writeString(componentClass.getName()); -+ } -+ os.writeVarInt(len); -+ boolean anyTypeMismatch = false; -+ for (i = 0; i < len; ++i) { -+ value = Array.get(o, i); -+ if (value != null && DataEncoder.typeFromClass(value.getClass()) == componentType) continue; -+ anyTypeMismatch = true; -+ break; -+ } -+ os.writeBoolean(anyTypeMismatch); -+ for (i = 0; i < len; ++i) { -+ DataEncoder.encode(os, Array.get(o, i), anyTypeMismatch); -+ } -+ break; -+ } -+ case Block: { -+ DataEncoder.encode(os, Util.getName((Block)o), false); -+ break; -+ } -+ case BlockPos: { -+ BlockPos pos = (BlockPos)o; -+ os.writeInt(pos.getX()); -+ os.writeInt(pos.getY()); -+ os.writeInt(pos.getZ()); -+ break; -+ } -+ case Boolean: { -+ os.writeBoolean((Boolean)o); -+ break; -+ } -+ case Byte: { -+ os.writeByte(((Byte)o).byteValue()); -+ break; -+ } -+ case Character: { -+ os.writeChar(((Character)o).charValue()); -+ break; -+ } -+ case ChunkPos: { -+ ChunkPos pos = (ChunkPos)o; -+ os.writeInt(pos.x); -+ os.writeInt(pos.z); -+ break; -+ } -+ case Collection: { -+ DataEncoder.encode(os, ((Collection)o).toArray(), false); -+ break; -+ } -+ case Component: { -+ NBTTagCompound nbt = ((TileEntityComponent)o).writeToNbt(); -+ DataEncoder.encode(os, nbt == null ? new NBTTagCompound() : nbt, false); -+ break; -+ } -+ case CropCard: { -+ CropCard cropCard = (CropCard)o; -+ os.writeString(cropCard.getOwner()); -+ os.writeString(cropCard.getId()); -+ break; -+ } -+ case Double: { -+ os.writeDouble((Double)o); -+ break; -+ } -+ case ElectrolyzerRecipe: { -+ IElectrolyzerRecipeManager.ElectrolyzerRecipe recipe = (IElectrolyzerRecipeManager.ElectrolyzerRecipe)o; -+ os.writeInt(recipe.inputAmount); -+ os.writeInt(recipe.EUaTick); -+ os.writeInt(recipe.ticksNeeded); -+ IElectrolyzerRecipeManager.ElectrolyzerOutput[] outputs = recipe.outputs; -+ os.writeByte(outputs.length); -+ for (IElectrolyzerRecipeManager.ElectrolyzerOutput output : outputs) { -+ os.writeString(output.fluidName); -+ os.writeInt(output.fluidAmount); -+ os.writeByte(output.tankDirection.getIndex()); -+ } -+ break; -+ } -+ case Enchantment: { -+ DataEncoder.encode(os, Enchantment.REGISTRY.getNameForObject(((Enchantment)o)), false); -+ break; -+ } -+ case Enum: { -+ os.writeVarInt(((Enum)o).ordinal()); -+ break; -+ } -+ case Float: { -+ os.writeFloat(((Float)o).floatValue()); -+ break; -+ } -+ case Fluid: { -+ os.writeString(((Fluid)o).getName()); -+ break; -+ } -+ case FluidStack: { -+ FluidStack fs = (FluidStack)o; -+ DataEncoder.encode(os, fs.getFluid(), false); -+ os.writeInt(fs.amount); -+ DataEncoder.encode(os, fs.tag, true); -+ break; -+ } -+ case FluidTank: { -+ FluidTank tank = (FluidTank)o; -+ DataEncoder.encode(os, tank.getFluid(), true); -+ os.writeInt(tank.getCapacity()); -+ break; -+ } -+ case GameProfile: { -+ GameProfile gp = (GameProfile)o; -+ DataEncoder.encode(os, gp.getId(), true); -+ os.writeString(gp.getName()); -+ break; -+ } -+ case Integer: { -+ os.writeInt((Integer)o); -+ break; -+ } -+ case InvSlot: { -+ InvSlot slot = (InvSlot)o; -+ ItemStack[] contents = new ItemStack[slot.size()]; -+ for (int i = 0; i < slot.size(); ++i) { -+ contents[i] = slot.get(i); -+ } -+ DataEncoder.encode(os, contents, false); -+ break; -+ } -+ case Item: { -+ DataEncoder.encode(os, Util.getName((Item)o), false); -+ break; -+ } -+ case ItemStack: { -+ ItemStack stack = (ItemStack)o; -+ if (StackUtil.isEmpty(stack)) { -+ os.writeByte(0); -+ break; -+ } -+ os.writeByte(StackUtil.getSize(stack)); -+ DataEncoder.encode(os, stack.getItem(), false); -+ os.writeShort(stack.getItemDamage()); -+ DataEncoder.encode(os, stack.getTagCompound(), true); -+ break; -+ } -+ case Long: { -+ os.writeLong((Long)o); -+ break; -+ } -+ case NBTTagCompound: { -+ CompressedStreamTools.write((NBTTagCompound)((NBTTagCompound)o), (DataOutput)os); -+ break; -+ } -+ case Null: { -+ if (withType) break; - throw new IllegalArgumentException("o has to be non-null without types"); +@@ -391,7 +391,7 @@ + final int i2 = is.readVarInt(); + boolean flag3 = is.readBoolean(); + boolean flag = !dataencoder$encodedtype.threadSafe; +- final Object object; ++ Object object; + if (!flag) { + object = Array.newInstance(oclass1, i2); + } else { +@@ -432,12 +432,13 @@ + return object; } -- break; -- case Object: -- throw new IllegalArgumentException("unhandled class: " + o.getClass()); -- case Potion: -- encode(os, Potion.REGISTRY.getNameForObject((Potion)o), false); -- break; -- case ResourceLocation: -- ResourceLocation resourcelocation = (ResourceLocation)o; -- os.writeString(resourcelocation.getResourceDomain()); -- os.writeString(resourcelocation.getResourcePath()); -- break; -- case Short: -- os.writeShort(((Short)o).shortValue()); -- break; -- case String: -- os.writeString((String)o); -- break; -- case TileEntity: -- TileEntity tileentity = (TileEntity)o; -- encode(os, tileentity.getWorld(), false); -- encode(os, tileentity.getPos(), false); -- break; -- case TupleT2: -- Tuple.T2 t2 = (Tuple.T2)o; -- encode(os, t2.a, true); -- encode(os, t2.b, true); -- break; -- case TupleT3: -- Tuple.T3 t3 = (Tuple.T3)o; -- encode(os, t3.a, true); -- encode(os, t3.b, true); -- encode(os, t3.c, true); -- break; -- case UUID: -- UUID uuid = (UUID)o; -- os.writeLong(uuid.getMostSignificantBits()); -- os.writeLong(uuid.getLeastSignificantBits()); -- break; -- case Vec3: -- Vec3d vec3d = (Vec3d)o; -- os.writeDouble(vec3d.x); -- os.writeDouble(vec3d.y); -- os.writeDouble(vec3d.z); -- break; -- case World: -- os.writeInt(((World)o).provider.getDimension()); -- break; -- default: -- throw new IllegalArgumentException("unhandled type: " + dataencoder$encodedtype); -- } -- -+ case Object: { -+ throw new IllegalArgumentException("unhandled class: " + o.getClass()); -+ } -+ case Potion: { -+ DataEncoder.encode(os, Potion.REGISTRY.getNameForObject(((Potion)o)), false); -+ break; -+ } -+ case ResourceLocation: { -+ ResourceLocation loc = (ResourceLocation)o; -+ os.writeString(loc.getResourceDomain()); -+ os.writeString(loc.getResourcePath()); -+ break; -+ } -+ case Short: { -+ os.writeShort(((Short)o).shortValue()); -+ break; -+ } -+ case String: { -+ os.writeString((String)o); -+ break; -+ } -+ case TileEntity: { -+ TileEntity te = (TileEntity)o; -+ DataEncoder.encode(os, te.getWorld(), false); -+ DataEncoder.encode(os, te.getPos(), false); -+ break; -+ } -+ case TupleT2: { -+ Tuple.T2 t = (Tuple.T2)o; -+ DataEncoder.encode(os, t.a, true); -+ DataEncoder.encode(os, t.b, true); -+ break; -+ } -+ case TupleT3: { -+ Tuple.T3 t = (Tuple.T3)o; -+ DataEncoder.encode(os, t.a, true); -+ DataEncoder.encode(os, t.b, true); -+ DataEncoder.encode(os, t.c, true); -+ break; -+ } -+ case UUID: { -+ UUID uuid = (UUID)o; -+ os.writeLong(uuid.getMostSignificantBits()); -+ os.writeLong(uuid.getLeastSignificantBits()); -+ break; -+ } -+ case Vec3: { -+ Vec3d v = (Vec3d)o; -+ os.writeDouble(v.x); -+ os.writeDouble(v.y); -+ os.writeDouble(v.z); -+ break; -+ } -+ case World: { -+ os.writeInt(((World)o).provider.getDimension()); -+ break; -+ } -+ default: { -+ throw new IllegalArgumentException("unhandled type: " + (Object)((Object)type)); -+ } -+ }*/ - } - public static Object decode(IGrowingBuffer is) throws IOException { - try { -- return decode(is, typeFromId(is.readUnsignedByte())); -- } catch (IllegalArgumentException illegalargumentexception) { -- String s = "An unknown data type was received over multiplayer to be decoded.\nThis could happen due to corrupted data or a bug."; -- IC2.platform.displayError(illegalargumentexception, s); -+ return DataEncoder.decode(is, DataEncoder.typeFromId(is.readByte())); -+ } -+ catch (IllegalArgumentException e) { -+ String msg = "An unknown data type was received over multiplayer to be decoded.\nThis could happen due to corrupted data or a bug."; -+ IC2.platform.displayError(e, msg, new Object[0]); - return null; - } - } ++ Object finalObject = object; + return new DataEncoder.IResolvableValue() { + public Object get() { + Object object3 = Array.newInstance(oclass, i2); - public static T decode(IGrowingBuffer is, Class clazz) throws IOException { -- DataEncoder.EncodedType dataencoder$encodedtype = typeFromClass(clazz); -- if (dataencoder$encodedtype.threadSafe) { -- return (T)decode(is, dataencoder$encodedtype); -- } else { -- throw new IllegalArgumentException("requesting decode for non thread safe type"); -+ EncodedType type = DataEncoder.typeFromClass(clazz); -+ if (type.threadSafe) { -+ return (T)DataEncoder.decode(is, type); - } -+ throw new IllegalArgumentException("requesting decode for non thread safe type"); - } - - public static > T decodeEnum(IGrowingBuffer is, Class clazz) throws IOException { -- int i = ((Integer)decode(is, DataEncoder.EncodedType.Enum)).intValue(); -- T[] at = clazz.getEnumConstants(); -- return (T)(i >= 0 && i < at.length ? at[i] : null); -+ int ordinal = (Integer)DataEncoder.decode(is, EncodedType.Enum); -+ Enum[] values = (Enum[])clazz.getEnumConstants(); -+ return (T)(ordinal >= 0 && ordinal < values.length ? values[ordinal] : null); - } - - public static Object decodeDeferred(GrowingBuffer is, Class clazz) throws IOException { -- DataEncoder.EncodedType dataencoder$encodedtype = typeFromClass(clazz); -- return decode(is, dataencoder$encodedtype); -+ EncodedType type = DataEncoder.typeFromClass(clazz); -+ return DataEncoder.decode((IGrowingBuffer)is, type); - } + for(int l2 = 0; l2 < i2; ++l2) { +- Array.set(object3, l2, DataEncoder.getValue(Array.get(object, l2))); ++ Array.set(object3, l2, DataEncoder.getValue(Array.get(finalObject, l2))); + } -- public static Object decode(final IGrowingBuffer is, DataEncoder.EncodedType type) throws IOException { -- switch(type) { -- case Addon: -- case UnSafeAddon: -- String s = is.readString(); -- final INetworkCustomEncoder inetworkcustomencoder = classToAddonType.get(getClass(s)); -- if (inetworkcustomencoder == null) { -- throw new IllegalStateException("Cannot decode an object without a decoder! Type was " + s); -- } else { -- if (inetworkcustomencoder.isThreadSafe()) { -- return inetworkcustomencoder.decode(is); -- } -+ public static Object decode(final IGrowingBuffer is, EncodedType type) throws IOException { -+ switch (type) { -+ case Addon: -+ case UnSafeAddon: { -+ String aimTypeName = is.readString(); -+ final INetworkCustomEncoder ince = classToAddonType.get(DataEncoder.getClass(aimTypeName)); -+ if (ince == null) { -+ throw new IllegalStateException("Cannot decode an object without a decoder! Type was " + aimTypeName); -+ } -+ if (ince.isThreadSafe()) { -+ return ince.decode(is); -+ } -+ return new IResolvableValue(){ + return object3; +@@ -467,7 +468,7 @@ -- return new DataEncoder.IResolvableValue() { -+ @Override - public Object get() { - try { -- return inetworkcustomencoder.decode(is); -- } catch (IOException ioexception) { -- throw new RuntimeException("Unexpected error", ioexception); -+ return ince.decode(is); -+ } -+ catch (IOException e) { -+ throw new RuntimeException("Unexpected error", e); - } - } - }; - } -- case Array: -- DataEncoder.EncodedType dataencoder$encodedtype = typeFromId(is.readUnsignedByte()); -- boolean flag1 = is.readBoolean(); -- boolean flag2 = dataencoder$encodedtype == DataEncoder.EncodedType.Enum; -- Class oclass1 = flag1 ? unbox(dataencoder$encodedtype.cls) : dataencoder$encodedtype.cls; -- if (oclass1 == null || flag2) { -- assert dataencoder$encodedtype == DataEncoder.EncodedType.Addon || dataencoder$encodedtype == DataEncoder.EncodedType.UnSafeAddon || flag2; -- -- oclass1 = getClass(is.readString()); -- } -- -- final Class oclass = oclass1; -- final int i2 = is.readVarInt(); -- boolean flag3 = is.readBoolean(); -- boolean flag = !dataencoder$encodedtype.threadSafe; -- final Object object; -- if (!flag) { -- object = Array.newInstance(oclass1, i2); -- } else { -- object = new Object[i2]; -- } -- -- if (!flag3) { -- if (flag2) { -- Object[] aobject = oclass1.getEnumConstants(); -- -- assert aobject != null; -- -- for(int k = 0; k < i2; ++k) { -- Array.set(object, k, aobject[((Integer)decode(is, dataencoder$encodedtype)).intValue()]); -+ case Array: { -+ Class component; -+ EncodedType componentType = DataEncoder.typeFromId(is.readUnsignedByte()); -+ boolean primitive = is.readBoolean(); -+ boolean isEnum = componentType == EncodedType.Enum; -+ Class clazz = component = primitive ? DataEncoder.unbox(componentType.cls) : componentType.cls; -+ if (component == null || isEnum) { -+ assert (componentType == EncodedType.Addon || componentType == EncodedType.UnSafeAddon || isEnum); -+ component = DataEncoder.getClass(is.readString()); -+ } -+ final Class componentClass = component; -+ final int len = is.readVarInt(); -+ boolean anyTypeMismatch = is.readBoolean(); -+ boolean needsResolving = !componentType.threadSafe; -+ Object array = !needsResolving ? Array.newInstance(componentClass, len) : new Object[len]; -+ if (!anyTypeMismatch) { -+ if (isEnum) { -+ Object[] constants = componentClass.getEnumConstants(); -+ assert (constants != null); -+ for (int i = 0; i < len; ++i) { -+ Array.set(array, i, constants[(Integer)DataEncoder.decode(is, componentType)]); -+ } -+ } else { -+ for (int i = 0; i < len; ++i) { -+ Array.set(array, i, DataEncoder.decode(is, componentType)); -+ } - } - } else { -- for(int j2 = 0; j2 < i2; ++j2) { -- Array.set(object, j2, decode(is, dataencoder$encodedtype)); -- } -- } -- } else { -- for(int k2 = 0; k2 < i2; ++k2) { -- DataEncoder.EncodedType dataencoder$encodedtype1 = typeFromId(is.readUnsignedByte()); -- if (!dataencoder$encodedtype1.threadSafe && !flag) { -- flag = true; -- if (oclass != Object.class) { -- Object object1 = new Object[i2]; -- System.arraycopy(object, 0, object1, 0, k2); -- object = object1; -- } -- } -- -- Array.set(object, k2, decode(is, dataencoder$encodedtype1)); -- } -- } -- -- if (!flag) { -- return object; -- } -- -- return new DataEncoder.IResolvableValue() { -- public Object get() { -- Object object3 = Array.newInstance(oclass, i2); -- -- for(int l2 = 0; l2 < i2; ++l2) { -- Array.set(object3, l2, DataEncoder.getValue(Array.get(object, l2))); -- } -- -- return object3; -- } -- }; -- case Block: -- return Util.getBlock((ResourceLocation)decode(is, DataEncoder.EncodedType.ResourceLocation)); -- case BlockPos: -- return new BlockPos(is.readInt(), is.readInt(), is.readInt()); -- case Boolean: -- return is.readBoolean(); -- case Byte: -- return is.readByte(); -- case Character: -- return is.readChar(); -- case ChunkPos: -- return new ChunkPos(is.readInt(), is.readInt()); -- case Collection: -- final Object object2 = decode(is, DataEncoder.EncodedType.Array); -- if (object2 instanceof DataEncoder.IResolvableValue) { -- return new DataEncoder.IResolvableValue>() { -- public List get() { -- return Arrays.asList(((DataEncoder.IResolvableValue)object2).get()); -- } -- }; -- } -- -- return Arrays.asList(object2); -- case Component: + return Arrays.asList(object2); + case Component: - return (List)decode(is, DataEncoder.EncodedType.NBTTagCompound); -- case CropCard: -- return Crops.instance.getCropCard(is.readString(), is.readString()); -- case Double: -- return is.readDouble(); -- case ElectrolyzerRecipe: -- int i1 = is.readInt(); -- int j1 = is.readInt(); -- int l1 = is.readInt(); -- byte b1 = is.readByte(); -- IElectrolyzerRecipeManager.ElectrolyzerOutput[] aielectrolyzerrecipemanager$electrolyzeroutput = new IElectrolyzerRecipeManager.ElectrolyzerOutput[b1]; -- -- for(byte b0 = 0; b0 < b1; ++b0) { -- aielectrolyzerrecipemanager$electrolyzeroutput[b0] = new IElectrolyzerRecipeManager.ElectrolyzerOutput(is.readString(), is.readInt(), EnumFacing.getFront(is.readByte())); -- } -- -- return new IElectrolyzerRecipeManager.ElectrolyzerRecipe(i1, j1, l1, aielectrolyzerrecipemanager$electrolyzeroutput); -- case Enchantment: -- return (List)Enchantment.REGISTRY.getObject((ResourceLocation)decode(is, DataEncoder.EncodedType.ResourceLocation)); -- case Enum: -- return is.readVarInt(); -- case Float: -- return is.readFloat(); -- case Fluid: -- return FluidRegistry.getFluid(is.readString()); -- case FluidStack: -- FluidStack fluidstack = new FluidStack((Fluid)decode(is, DataEncoder.EncodedType.Fluid), is.readInt()); -- fluidstack.tag = (NBTTagCompound)decode(is); -- return fluidstack; -- case FluidTank: -- return new FluidTank((FluidStack)decode(is), is.readInt()); -- case GameProfile: -- return new GameProfile((UUID)decode(is), is.readString()); -- case Integer: -- return is.readInt(); -- case InvSlot: -- ItemStack[] aitemstack = (ItemStack[])decode(is, DataEncoder.EncodedType.Array); -- InvSlot invslot = new InvSlot(aitemstack.length); -- -- for(int k1 = 0; k1 < aitemstack.length; ++k1) { -- invslot.put(k1, aitemstack[k1]); -- } -- -- return invslot; -- case Item: -- return Util.getItem((ResourceLocation)decode(is, DataEncoder.EncodedType.ResourceLocation)); -- case ItemStack: -- int l = is.readByte(); -- if (l == 0) { -- return StackUtil.emptyStack; -- } -- -- Item item = (Item)decode(is, Item.class); -- int j = is.readShort(); -- NBTTagCompound nbttagcompound = (NBTTagCompound)decode(is); -- ItemStack itemstack = new ItemStack(item, l, j); -- itemstack.setTagCompound(nbttagcompound); -- return itemstack; -- case Long: -- return is.readLong(); -- case NBTTagCompound: -- return CompressedStreamTools.read(is, NBTSizeTracker.INFINITE); -- case Null: -- return null; -- case Object: -- return (List)(new Object()); -- case Potion: -- return (List)Potion.REGISTRY.getObject((ResourceLocation)decode(is, DataEncoder.EncodedType.ResourceLocation)); -- case ResourceLocation: -- return new ResourceLocation(is.readString(), is.readString()); -- case Short: -- return is.readShort(); -- case String: -- return is.readString(); -- case TileEntity: -- final DataEncoder.IResolvableValue iresolvablevalue = (DataEncoder.IResolvableValue)decode(is, DataEncoder.EncodedType.World); -- final BlockPos blockpos = (BlockPos)decode(is, DataEncoder.EncodedType.BlockPos); -- return new DataEncoder.IResolvableValue() { -- public TileEntity get() { -- World world = iresolvablevalue.get(); -- return world == null ? null : world.getTileEntity(blockpos); -- } -- }; -- case TupleT2: -- return new Tuple.T2(decode(is), decode(is)); -- case TupleT3: -- return new Tuple.T3(decode(is), decode(is), decode(is)); -- case UUID: -- return new UUID(is.readLong(), is.readLong()); -- case Vec3: -- return new Vec3d(is.readDouble(), is.readDouble(), is.readDouble()); -- case World: -- final int i = is.readInt(); -- return new DataEncoder.IResolvableValue() { -- public World get() { -- return IC2.platform.getWorld(i); -- } -- }; -- default: -- throw new IllegalArgumentException("unhandled type: " + type); -+ for (int i = 0; i < len; ++i) { -+ EncodedType cType = DataEncoder.typeFromId(is.readUnsignedByte()); -+ if (!cType.threadSafe && !needsResolving) { -+ needsResolving = true; -+ if (componentClass != Object.class) { -+ Object[] newArray = new Object[len]; -+ System.arraycopy(array, 0, newArray, 0, i); -+ array = newArray; -+ } -+ } -+ Array.set(array, i, DataEncoder.decode(is, cType)); -+ } -+ } -+ if (!needsResolving) { -+ return array; ++ return decode(is, DataEncoder.EncodedType.NBTTagCompound); + case CropCard: + return Crops.instance.getCropCard(is.readString(), is.readString()); + case Double: +@@ -587,40 +588,38 @@ + } else { + return false; + } ++ } else if (dst instanceof FluidTank) { ++ FluidTank fluidtank = (FluidTank)src; ++ FluidTank fluidtank1 = (FluidTank)dst; ++ fluidtank1.setFluid(fluidtank.getFluid()); ++ fluidtank1.setCapacity(fluidtank.getCapacity()); ++ } else if (dst instanceof InvSlot) { ++ InvSlot invslot = (InvSlot)src; ++ InvSlot invslot1 = (InvSlot)dst; ++ if (invslot.size() != invslot1.size()) { ++ throw new RuntimeException("Can't sync InvSlots with mismatched sizes."); + } -+ final Object tmpArray = array; -+ return new IResolvableValue(){ + -+ @Override -+ public Object get() { -+ Object ret = Array.newInstance(componentClass, len); -+ for (int i = 0; i < len; ++i) { -+ Array.set(ret, i, DataEncoder.getValue(Array.get(tmpArray, i))); -+ } -+ return ret; ++ for(int i = 0; i < invslot.size(); ++i) { ++ if (!copyValue(invslot.get(i), invslot1.get(i))) { ++ invslot1.put(i, invslot.get(i)); + } -+ }; -+ } -+ case Block: { -+ return Util.getBlock((ResourceLocation)DataEncoder.decode(is, EncodedType.ResourceLocation)); -+ } -+ case BlockPos: { -+ return new BlockPos(is.readInt(), is.readInt(), is.readInt()); -+ } -+ case Boolean: { -+ return is.readBoolean(); -+ } -+ case Byte: { -+ return is.readByte(); -+ } -+ case Character: { -+ return Character.valueOf(is.readChar()); -+ } -+ case ChunkPos: { -+ return new ChunkPos(is.readInt(), is.readInt()); -+ } -+ case Collection: { -+ final Object ret = DataEncoder.decode(is, EncodedType.Array); -+ if (ret instanceof IResolvableValue) { -+ return new IResolvableValue>(){ -+ -+ @Override -+ public List get() { -+ return Arrays.asList((Object[])((IResolvableValue)ret).get()); -+ } -+ }; -+ } -+ return Arrays.asList((Object[])ret); -+ } -+ case Component: { -+ return DataEncoder.decode(is, EncodedType.NBTTagCompound); -+ } -+ case CropCard: { -+ return Crops.instance.getCropCard(is.readString(), is.readString()); -+ } -+ case Double: { -+ return is.readDouble(); -+ } -+ case ElectrolyzerRecipe: { -+ int inputAmount = is.readInt(); -+ int EUaTick = is.readInt(); -+ int ticksNeeded = is.readInt(); -+ byte max = is.readByte(); -+ IElectrolyzerRecipeManager.ElectrolyzerOutput[] outputs = new IElectrolyzerRecipeManager.ElectrolyzerOutput[max]; -+ for (byte i = 0; i < max; i = (byte)(i + 1)) { -+ outputs[i] = new IElectrolyzerRecipeManager.ElectrolyzerOutput(is.readString(), is.readInt(), EnumFacing.getFront((int)is.readByte())); -+ } -+ return new IElectrolyzerRecipeManager.ElectrolyzerRecipe(inputAmount, EUaTick, ticksNeeded, outputs); -+ } -+ case Enchantment: { -+ return Enchantment.REGISTRY.getObject(((ResourceLocation)DataEncoder.decode(is, EncodedType.ResourceLocation))); -+ } -+ case Enum: { -+ return is.readVarInt(); -+ } -+ case Float: { -+ return Float.valueOf(is.readFloat()); -+ } -+ case Fluid: { -+ return FluidRegistry.getFluid((String)is.readString()); -+ } -+ case FluidStack: { -+ FluidStack ret = new FluidStack((Fluid)DataEncoder.decode(is, EncodedType.Fluid), is.readInt()); -+ ret.tag = (NBTTagCompound)DataEncoder.decode(is); -+ return ret; -+ } -+ case FluidTank: { -+ return new FluidTank((FluidStack)DataEncoder.decode(is), is.readInt()); -+ } -+ case GameProfile: { -+ return new GameProfile((UUID)DataEncoder.decode(is), is.readString()); -+ } -+ case Integer: { -+ return is.readInt(); -+ } -+ case InvSlot: { -+ ItemStack[] contents = (ItemStack[])DataEncoder.decode(is, EncodedType.Array); -+ InvSlot ret = new InvSlot(contents.length); -+ for (int i = 0; i < contents.length; ++i) { -+ ret.put(i, contents[i]); + } -+ return ret; -+ } -+ case Item: { -+ return Util.getItem((ResourceLocation)DataEncoder.decode(is, EncodedType.ResourceLocation)); -+ } -+ case ItemStack: { -+ byte size = is.readByte(); -+ if (size == 0) { -+ return StackUtil.emptyStack; -+ } -+ Item item = DataEncoder.decode(is, Item.class); -+ short meta = is.readShort(); -+ NBTTagCompound nbt = (NBTTagCompound)DataEncoder.decode(is); -+ ItemStack ret = new ItemStack(item, (int)size, (int)meta); -+ ret.setTagCompound(nbt); -+ return ret; -+ } -+ case Long: { -+ return is.readLong(); -+ } -+ case NBTTagCompound: { -+ return CompressedStreamTools.read((DataInput)is, (NBTSizeTracker)NBTSizeTracker.INFINITE); -+ } -+ case Null: { -+ return null; -+ } -+ case Object: { -+ return new Object(); -+ } -+ case Potion: { -+ return Potion.REGISTRY.getObject(((ResourceLocation)DataEncoder.decode(is, EncodedType.ResourceLocation))); -+ } -+ case ResourceLocation: { -+ return new ResourceLocation(is.readString(), is.readString()); -+ } -+ case Short: { -+ return is.readShort(); -+ } -+ case String: { -+ return is.readString(); -+ } -+ case TileEntity: { -+ final IResolvableValue deferredWorld = (IResolvableValue)DataEncoder.decode(is, EncodedType.World); -+ final BlockPos pos = (BlockPos)DataEncoder.decode(is, EncodedType.BlockPos); -+ return new IResolvableValue(){ -+ -+ @Override -+ public TileEntity get() { -+ World world = (World)deferredWorld.get(); -+ if (world == null) { -+ return null; -+ } -+ return world.getTileEntity(pos); -+ } -+ }; -+ } -+ case TupleT2: { -+ return new Tuple.T2(DataEncoder.decode(is), DataEncoder.decode(is)); -+ } -+ case TupleT3: { -+ return new Tuple.T3(DataEncoder.decode(is), DataEncoder.decode(is), DataEncoder.decode(is)); -+ } -+ case UUID: { -+ return new UUID(is.readLong(), is.readLong()); -+ } -+ case Vec3: { -+ return new Vec3d(is.readDouble(), is.readDouble(), is.readDouble()); -+ } -+ case World: { -+ final int dimensionId = is.readInt(); -+ return new IResolvableValue(){ -+ -+ @Override -+ public World get() { -+ return IC2.platform.getWorld(dimensionId); -+ } -+ }; -+ } - } -+ throw new IllegalArgumentException("unhandled type: " + (Object)((Object)type)); - } - - public static T getValue(Object decoded) { -- return (T)(decoded instanceof DataEncoder.IResolvableValue ? ((DataEncoder.IResolvableValue)decoded).get() : decoded); -+ if (decoded instanceof IResolvableValue) { -+ return (T) ((IResolvableValue)decoded).get(); -+ } -+ return (T)decoded; - } - - public static boolean copyValue(T src, T dst) { -- if (src != null && dst != null) { -- if (dst instanceof ItemStack) { -- ItemStack itemstack = (ItemStack)src; -- ItemStack itemstack1 = (ItemStack)dst; -- if (itemstack.getItem() == itemstack1.getItem()) { -- itemstack1.setCount(itemstack.getCount()); -- StackUtil.setRawMeta(itemstack1, StackUtil.getRawMeta(itemstack)); -- itemstack1.setTagCompound(itemstack.getTagCompound()); -- return true; -- } else { -- return false; -- } -- } else { ++ } else if (dst instanceof TileEntityComponent) { ++ NBTTagCompound nbttagcompound = (NBTTagCompound)src; ++ ((TileEntityComponent)dst).readFromNbt(nbttagcompound); + } else { - if (dst instanceof FluidTank) { - FluidTank fluidtank = (FluidTank)src; - FluidTank fluidtank1 = (FluidTank)dst; @@ -1125,297 +87,18 @@ - Collection collection1 = (Collection)dst; - collection1.clear(); - collection1.addAll(collection); -- } -- -+ if (src == null || dst == null) { -+ return false; -+ } -+ if (dst instanceof ItemStack) { -+ ItemStack srcT = (ItemStack)src; -+ ItemStack dstT = (ItemStack)dst; -+ if (srcT.getItem() == dstT.getItem()) { -+ dstT.setCount(srcT.getCount()); -+ StackUtil.setRawMeta(dstT, StackUtil.getRawMeta(srcT)); -+ dstT.setTagCompound(srcT.getTagCompound()); - return true; ++ if (!(dst instanceof Collection)) { ++ return false; + } + +- return true; ++ Collection collection = (Collection)src; ++ Collection collection1 = (Collection)dst; ++ collection1.clear(); ++ collection1.addAll(collection); } -+ return false; -+ } -+ if (dst instanceof FluidTank) { -+ FluidTank srcT = (FluidTank)src; -+ FluidTank dstT = (FluidTank)dst; -+ dstT.setFluid(srcT.getFluid()); -+ dstT.setCapacity(srcT.getCapacity()); -+ } else if (dst instanceof InvSlot) { -+ InvSlot srcT = (InvSlot)src; -+ InvSlot dstT = (InvSlot)dst; -+ if (srcT.size() != dstT.size()) { -+ throw new RuntimeException("Can't sync InvSlots with mismatched sizes."); -+ } -+ for (int i = 0; i < srcT.size(); ++i) { -+ if (DataEncoder.copyValue(srcT.get(i), dstT.get(i))) continue; -+ dstT.put(i, srcT.get(i)); -+ } -+ } else if (dst instanceof TileEntityComponent) { -+ NBTTagCompound nbt = (NBTTagCompound)src; -+ ((TileEntityComponent)dst).readFromNbt(nbt); -+ } else if (dst instanceof Collection) { -+ Collection srcT = (Collection)src; -+ Collection dstT = (Collection)dst; -+ dstT.clear(); -+ dstT.addAll(srcT); ++ ++ return true; } else { return false; } -+ return true; - } - - private static Class box(Class clazz) { - if (clazz == Byte.TYPE) { - return Byte.class; -- } else if (clazz == Short.TYPE) { -+ } -+ if (clazz == Short.TYPE) { - return Short.class; -- } else if (clazz == Integer.TYPE) { -+ } -+ if (clazz == Integer.TYPE) { - return Integer.class; -- } else if (clazz == Long.TYPE) { -+ } -+ if (clazz == Long.TYPE) { - return Long.class; -- } else if (clazz == Float.TYPE) { -+ } -+ if (clazz == Float.TYPE) { - return Float.class; -- } else if (clazz == Double.TYPE) { -+ } -+ if (clazz == Double.TYPE) { - return Double.class; -- } else if (clazz == Boolean.TYPE) { -+ } -+ if (clazz == Boolean.TYPE) { - return Boolean.class; -- } else { -- return clazz == Character.TYPE ? Character.class : clazz; -- } -+ } -+ if (clazz == Character.TYPE) { -+ return Character.class; -+ } -+ return clazz; - } - - private static Class unbox(Class clazz) { - if (clazz == Byte.class) { - return Byte.TYPE; -- } else if (clazz == Short.class) { -+ } -+ if (clazz == Short.class) { - return Short.TYPE; -- } else if (clazz == Integer.class) { -+ } -+ if (clazz == Integer.class) { - return Integer.TYPE; -- } else if (clazz == Long.class) { -+ } -+ if (clazz == Long.class) { - return Long.TYPE; -- } else if (clazz == Float.class) { -+ } -+ if (clazz == Float.class) { - return Float.TYPE; -- } else if (clazz == Double.class) { -+ } -+ if (clazz == Double.class) { - return Double.TYPE; -- } else if (clazz == Boolean.class) { -+ } -+ if (clazz == Boolean.class) { - return Boolean.TYPE; -- } else { -- return clazz == Character.class ? Character.TYPE : clazz; -- } -+ } -+ if (clazz == Character.class) { -+ return Character.TYPE; -+ } -+ return clazz; - } - - private static Class getClass(String type) { - try { - return Class.forName(type); -- } catch (ClassNotFoundException classnotfoundexception) { -- throw new RuntimeException("Missing type from the class path expected by network: " + type, classnotfoundexception); -+ } -+ catch (ClassNotFoundException e) { -+ throw new RuntimeException("Missing type from the class path expected by network: " + type, e); - } - } - -- private static int idFromType(DataEncoder.EncodedType type) { -+ private static int idFromType(EncodedType type) { - return type.ordinal(); - } - -- private static DataEncoder.EncodedType typeFromId(int id) { -- if (id >= 0 && id < DataEncoder.EncodedType.types.length) { -- return DataEncoder.EncodedType.types[id]; -- } else { -+ private static EncodedType typeFromId(int id) { -+ if (id < 0 || id >= EncodedType.types.length) { - throw new IllegalArgumentException("invalid type id: " + id); - } -- } -- -- private static DataEncoder.EncodedType typeFromObject(Object o) { -- return o == null ? DataEncoder.EncodedType.Null : typeFromClass(o.getClass()); -- } -- -- private static DataEncoder.EncodedType typeFromClass(Class cls) { -+ return EncodedType.types[id]; -+ } -+ -+ private static EncodedType typeFromObject(Object o) { -+ if (o == null) { -+ return EncodedType.Null; -+ } -+ return DataEncoder.typeFromClass(o.getClass()); -+ } -+ -+ private static EncodedType typeFromClass(Class cls) { -+ EncodedType ret; - if (cls == null) { -- return DataEncoder.EncodedType.Null; -- } else if (cls.isArray()) { -- return DataEncoder.EncodedType.Array; -- } else { -- if (cls.isPrimitive()) { -- cls = box(cls); -- } -- -- DataEncoder.EncodedType dataencoder$encodedtype = DataEncoder.EncodedType.classToTypeMap.get(cls); -- if (dataencoder$encodedtype != null) { -- return dataencoder$encodedtype; -- } else { -- dataencoder$encodedtype = classToTypeCache.get(cls); -- if (dataencoder$encodedtype != null) { -- return dataencoder$encodedtype; -- } else { -- INetworkCustomEncoder inetworkcustomencoder = classToAddonType.get(cls); -- if (inetworkcustomencoder != null) { -- dataencoder$encodedtype = inetworkcustomencoder.isThreadSafe() ? DataEncoder.EncodedType.Addon : DataEncoder.EncodedType.UnSafeAddon; -- classToTypeCache.put(cls, dataencoder$encodedtype); -- return dataencoder$encodedtype; -- } else { -- for(DataEncoder.EncodedType dataencoder$encodedtype1 : DataEncoder.EncodedType.types) { -- if (dataencoder$encodedtype1.cls != null && dataencoder$encodedtype1.cls.isAssignableFrom(cls)) { -- classToTypeCache.put(cls, dataencoder$encodedtype1); -- return dataencoder$encodedtype1; -- } -- } -- -- throw new IllegalStateException("unmatched " + cls); -- } -- } -- } -- } -+ return EncodedType.Null; -+ } -+ if (cls.isArray()) { -+ return EncodedType.Array; -+ } -+ if (cls.isPrimitive()) { -+ cls = DataEncoder.box(cls); -+ } -+ if ((ret = EncodedType.classToTypeMap.get(cls)) != null) { -+ return ret; -+ } -+ ret = classToTypeCache.get(cls); -+ if (ret != null) { -+ return ret; -+ } -+ INetworkCustomEncoder ince = classToAddonType.get(cls); -+ if (ince != null) { -+ ret = ince.isThreadSafe() ? EncodedType.Addon : EncodedType.UnSafeAddon; -+ classToTypeCache.put(cls, ret); -+ return ret; -+ } -+ for (EncodedType type : EncodedType.types) { -+ if (type.cls == null || !type.cls.isAssignableFrom(cls)) continue; -+ classToTypeCache.put(cls, type); -+ return type; -+ } -+ throw new IllegalStateException("unmatched " + cls); - } - - public static void addNetworkEncoder(Class typeBeingEncoded, INetworkCustomEncoder customEncoder) { -- assert typeBeingEncoded != null && customEncoder != null; -- -- INetworkCustomEncoder inetworkcustomencoder = classToAddonType.put(typeBeingEncoded, customEncoder); -- if (inetworkcustomencoder != null) { -- throw new IllegalStateException("Duplicate mapping for class! " + inetworkcustomencoder.getClass().getName() + " and " + customEncoder.getClass().getName() + " both map for " + typeBeingEncoded.getName() + '.'); -+ assert (typeBeingEncoded != null && customEncoder != null); -+ INetworkCustomEncoder previous = classToAddonType.put(typeBeingEncoded, customEncoder); -+ if (previous != null) { -+ throw new IllegalStateException("Duplicate mapping for class! " + previous.getClass().getName() + " and " + customEncoder.getClass().getName() + " both map for " + typeBeingEncoded.getName() + '.'); - } - } - - public static enum EncodedType { -- Null((Class)null), -- Array((Class)null), -+ Null(null), -+ Array(null), - Byte(Byte.class), - Short(Short.class), - Integer(Integer.class), -@@ -773,15 +832,15 @@ - ElectrolyzerRecipe(IElectrolyzerRecipeManager.ElectrolyzerRecipe.class), - TupleT2(Tuple.T2.class), - TupleT3(Tuple.T3.class), -- Addon((Class)null), -- UnSafeAddon((Class)null, false), -+ Addon(null), -+ UnSafeAddon(null, false), - Collection(Collection.class), - Object(Object.class); - - final Class cls; - final boolean threadSafe; -- static final DataEncoder.EncodedType[] types = values(); -- static final Map, DataEncoder.EncodedType> classToTypeMap = new IdentityHashMap, DataEncoder.EncodedType>(types.length - 2); -+ static final EncodedType[] types; -+ static final Map, EncodedType> classToTypeMap; - - private EncodedType(Class cls) { - this(cls, true); -@@ -793,19 +852,19 @@ - } - - static { -- for(DataEncoder.EncodedType dataencoder$encodedtype : types) { -- if (dataencoder$encodedtype.cls != null) { -- classToTypeMap.put(dataencoder$encodedtype.cls, dataencoder$encodedtype); -- } -+ types = EncodedType.values(); -+ classToTypeMap = new IdentityHashMap(types.length - 2); -+ for (EncodedType type : types) { -+ if (type.cls == null) continue; -+ classToTypeMap.put(type.cls, type); - } -- - if (types.length > 255) { - throw new RuntimeException("too many types"); - } - } - } - -- private interface IResolvableValue { -- T get(); -+ private static interface IResolvableValue { -+ public T get(); - } - } diff --git a/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/network/GrowingBuffer.java.patch b/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/network/GrowingBuffer.java.patch index a816a47..bd6c69d 100644 --- a/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/network/GrowingBuffer.java.patch +++ b/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/core/network/GrowingBuffer.java.patch @@ -1,11 +1,26 @@ --- a/ic2/core/network/GrowingBuffer.java +++ b/ic2/core/network/GrowingBuffer.java -@@ -214,7 +214,7 @@ +@@ -213,18 +213,15 @@ + if (i < 0) { throw new IllegalArgumentException("only positive numbers are supported"); } else { - while(true) { +- while(true) { - int i = i & 127; -+ i = i & 127; ++ do { ++ int part = i & 127; i >>>= 7; if (i != 0) { - i |= 128; +- i |= 128; ++ part |= 128; + } + +- this.writeByte(i); +- if (i == 0) { +- break; +- } +- } ++ this.writeByte(part); ++ } while(i != 0); + + } + } diff --git a/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/jeiIntegration/transferhandlers/TransferHandlerBatchCrafter.java.patch b/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/jeiIntegration/transferhandlers/TransferHandlerBatchCrafter.java.patch new file mode 100644 index 0000000..2bb6ffe --- /dev/null +++ b/projects/IC2-Base/patches[2.8.221,+]/minecraft/ic2/jeiIntegration/transferhandlers/TransferHandlerBatchCrafter.java.patch @@ -0,0 +1,45 @@ +--- a/ic2/jeiIntegration/transferhandlers/TransferHandlerBatchCrafter.java ++++ b/ic2/jeiIntegration/transferhandlers/TransferHandlerBatchCrafter.java +@@ -2,8 +2,6 @@ + + import ic2.core.IC2; + import ic2.core.block.machine.container.ContainerBatchCrafter; +-import ic2.core.block.machine.tileentity.TileEntityBatchCrafter; +-import ic2.core.network.NetworkManager; + import ic2.core.util.StackUtil; + import java.util.Map; + import mezz.jei.api.gui.IGuiIngredient; +@@ -13,7 +11,6 @@ + import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; + import net.minecraft.entity.player.EntityPlayer; + import net.minecraft.item.ItemStack; +-import net.minecraft.tileentity.TileEntity; + + public class TransferHandlerBatchCrafter implements IRecipeTransferHandler { + public Class getContainerClass() { +@@ -28,19 +25,19 @@ + Map> map = iguiitemstackgroup.getGuiIngredients(); + + for(int i = 0; i < 9; ++i) { +- IGuiIngredient iguiingredient = (IGuiIngredient)map.get(Integer.valueOf(i + 1)); ++ IGuiIngredient iguiingredient = map.get(i + 1); + ItemStack itemstack; + if (iguiingredient != null) { +- itemstack = (ItemStack)iguiingredient.getDisplayedIngredient(); ++ itemstack = iguiingredient.getDisplayedIngredient(); + } else { + itemstack = StackUtil.emptyStack; + } + +- ((TileEntityBatchCrafter)container.base).craftingGrid[i] = itemstack; ++ container.base.craftingGrid[i] = itemstack; + } +- +- ((NetworkManager)IC2.network.get(false)).updateTileEntityField((TileEntity)container.base, "craftingGrid"); +- ((NetworkManager)IC2.network.get(false)).initiateClientTileEntityEvent((TileEntity)container.base, 0); ++ ++ IC2.network.get(false).updateTileEntityField(container.base, "craftingGrid"); ++ IC2.network.get(false).initiateClientTileEntityEvent(container.base, 0); + return null; + } + } diff --git a/projects/IC2-Patched/build.gradle.kts b/projects/IC2-Patched/build.gradle.kts index 7586991..2df1289 100644 --- a/projects/IC2-Patched/build.gradle.kts +++ b/projects/IC2-Patched/build.gradle.kts @@ -1,18 +1,22 @@ import codechicken.diffpatch.util.PatchMode -import net.minecraftforge.gradle.patcher.task.TaskApplyPatches -import net.minecraftforge.gradle.patcher.task.TaskGeneratePatches import org.apache.commons.io.FileUtils +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import net.minecraftforge.gradle.patcher.tasks.GenerateBinPatches +import net.minecraftforge.gradle.patcher.tasks.GeneratePatches +import net.minecraftforge.gradle.patcher.tasks.ApplyPatches +import net.minecraftforge.gradle.mcp.tasks.GenerateSRG import java.nio.file.Files import java.nio.file.Path -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import net.minecraftforge.gradle.patcher.task.GenerateBinPatches -import net.minecraftforge.gradle.mcp.task.GenerateSRG +import java.util.jar.JarFile +import java.util.jar.JarOutputStream +import java.util.regex.Pattern plugins { java id("de.undercouch.download") id("net.minecraftforge.gradle") id("com.github.johnrengelman.shadow") version "7.1.2" + id("wtf.gofancy.fancygradle") } evaluationDependsOn(":IC2-Base") @@ -40,18 +44,28 @@ minecraft { mappings(mappingsChannel, mappingsVersion) } +fancyGradle { + patches { + asm + codeChickenLib + coremods + resources + mergetool + } +} + tasks { - register("applyPatches") { + register("applyPatches") { val baseSourceJar = project(":IC2-Base").tasks.getByName("sourceJarWithResources") dependsOn(baseSourceJar) - + group = taskGroup - base = baseSourceJar.archiveFile.get().asFile - patches = patchesDir - rejects = File(buildDir, "$name/rejects.zip") - output = patchedJar - patchMode = PatchMode.OFFSET - + base.set(baseSourceJar.archiveFile.get().asFile) + patches.set(patchesDir) + rejects.set(File(buildDir, "$name/rejects.zip")) + output.set(patchedJar) + patchMode.set(PatchMode.OFFSET) + isPrintSummary = true } @@ -87,7 +101,7 @@ tasks { from(sourceSets.main.get().allSource) } - register("generatePatches") { + register("generatePatches") { group = taskGroup val baseSourceJar = project(":IC2-Base").tasks.getByName("sourceJar") val sourceJar = getByName("sourceJar") @@ -95,15 +109,15 @@ tasks { dependsOn(sourceJar) dependsOn(baseSourceJar) - base = baseSourceJar.archiveFile.get().asFile - modified = sourceJar.archiveFile.get().asFile - output = outputDir + base.set(baseSourceJar.archiveFile.get().asFile) + modified.set(sourceJar.archiveFile.get().asFile) + output.set(outputDir) isPrintSummary = true - + doLast { val outputPath = outputDir.toPath() Files.walk(outputPath) - .filter { path -> + .filter { path -> val relative = outputPath.relativize(path).toString() relative.isNotEmpty() && (!relative.startsWith("ic2") || relative.startsWith("ic2\\profiles") || relative.startsWith("ic2\\sounds")) && path.toFile().isDirectory } @@ -132,22 +146,87 @@ tasks { register("generateBinPatches") { dependsOn("reobfJar") group = taskGroup - cleanJar = ic2Clean.singleFile - dirtyJar = File(buildDir, "reobfJar/output.jar") - output = File(rootDir, "src/main/generatedResources/patches/" + getPatchesDirectory() + "/ic2patches.pack.lzma") + cleanJar.set(ic2Clean.singleFile) + dirtyJar.set(File(buildDir, "reobfJar/output.jar")) + output.set(File(rootDir, "src/main/generatedResources/patches/" + getPatchesDirectory() + "/ic2patches.pack.lzma")) configureBinPatchTask(this) } - + register("generateDevBinPatches") { val shadowJar = getByName("shadowJar") dependsOn(shadowJar) group = taskGroup - cleanJar = ic2Dev.singleFile - dirtyJar = shadowJar.archiveFile.get().asFile - output = File(buildDir, "$name/patches/" + getPatchesDirectory() + "/ic2patches.pack.lzma") + cleanJar.set(ic2Dev.singleFile) + dirtyJar.set(shadowJar.archiveFile.get().asFile) + output.set(File(buildDir, "$name/patches/" + getPatchesDirectory() + "/ic2patches.pack.lzma")) configureBinPatchTask(this) } - + + /** + * Used to replace classes in the jar used for running the game in the IDE. + * Some classes (like networking) aren't functional after recompiling them, so those are getting replaced. + */ + register("patchRunJar") { + val shadowJar = getByName("shadowJar") + dependsOn(shadowJar) + mustRunAfter(shadowJar) + + val projectJarFile = shadowJar.archiveFile.get().asFile + val patchedJar = File(projectJarFile.toString().replace(".jar", "-patched.jar")) + + //TODO: Add separation between versions, so you can specify version range for replacement classes. For now those are required classes for 164 to boot. + val classesToReplace = listOf("assets/.*", "ic2/sounds/.*") + val tries = 3; + + doLast { for (i in 1 until tries+1) { try { + val patchedOut = JarOutputStream(patchedJar.outputStream()) + val projectJar = JarFile(projectJarFile) + val sourceJar = JarFile(ic2Dev.singleFile) + val stats = HashMap() + classesToReplace.forEach { regex -> stats[regex] = 0 } + + projectJar.use { input -> sourceJar.use { inputOg -> + val entries = input.entries() + val sourceEntries = ArrayList() + for (entry in inputOg.entries()) sourceEntries.add(entry.name) + while (entries.hasMoreElements()) { + var entry = entries.nextElement() + var replaced = false + + for (regex in classesToReplace) { + if (Pattern.matches(regex, entry.name) && !entry.name.endsWith("/")) { + if (sourceEntries.contains(entry.name)) { + entry = sourceJar.getJarEntry(entry.name); + patchedOut.putNextEntry(entry) + patchedOut.write(sourceJar.getInputStream(entry).readBytes()) + replaced = true + stats[regex] = (stats[regex] ?: 0) + 1 + } else { + println("Couldn't find entry " + entry.name + " in original jar!") + } + break + } + } + if (!replaced) { + patchedOut.putNextEntry(entry) + patchedOut.write(projectJar.getInputStream(entry).readBytes()) + } + patchedOut.closeEntry() + } + patchedOut.close() + println("Attempt $i was successful! Out of " + input.size() + " entries replaced:") + stats.forEach { (key, value) -> println("> $value entries under regex $key") } + } } + projectJar.close() + Files.delete(projectJarFile.toPath()) + Files.move(patchedJar.toPath(), projectJarFile.toPath()) + break + } catch (e: Exception) { + if (i >= tries) throw e + println("Exception caught while trying to patch run jar. Attempt: $i | Message: " + e.localizedMessage) + } } } + } + named("compileJava") { dependsOn("setup") } @@ -160,20 +239,20 @@ tasks { fun configureBinPatchTask(task: GenerateBinPatches) { val createMcpToSrg = tasks.getByName("createMcpToSrg") task.dependsOn(createMcpToSrg) - task.addPatchSet(patchesDir) - - task.args = arrayOf( - "--output", "{output}", - "--patches", "{patches}", +// task.addPatchSet(patchesDir) + task.patchSets.setFrom(patchesDir) + + task.args.set(listOf( + "--output", "{output}", + "--patches", "{patches}", "--srg", "{srg}", "--legacy", - - "--clean", "{clean}", + "--clean", "{clean}", "--create", "{dirty}", "--prefix", "binpatch/merged" - ) - - task.srg = createMcpToSrg.output + )) + + task.srg.set(createMcpToSrg.output) } reobf { @@ -186,7 +265,7 @@ repositories { mavenCentral() maven { name = "ic2" - url = uri("https://maven.ic2.player.to/") + url = uri("https://maven2.ic2.player.to/") } maven { name = "Progwml6 maven" diff --git a/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/invslot/InvSlotDischarge.java.patch b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/invslot/InvSlotDischarge.java.patch new file mode 100644 index 0000000..5416be2 --- /dev/null +++ b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/invslot/InvSlotDischarge.java.patch @@ -0,0 +1,18 @@ +--- a/ic2/core/block/invslot/InvSlotDischarge.java ++++ b/ic2/core/block/invslot/InvSlotDischarge.java +@@ -9,6 +9,7 @@ + import net.minecraft.item.ItemStack; + + public class InvSlotDischarge extends InvSlot implements IDischargingSlot { ++ public int baseTier; + public int tier; + public boolean allowRedstoneDust; + +@@ -24,6 +25,7 @@ + super(base, "discharge", access, 1, preferredSide); + this.allowRedstoneDust = true; + this.tier = tier; ++ this.baseTier = tier; + this.allowRedstoneDust = allowRedstoneDust; + } + diff --git a/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/invslot/InvSlotUpgrade.java.patch b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/invslot/InvSlotUpgrade.java.patch new file mode 100644 index 0000000..5916481 --- /dev/null +++ b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/invslot/InvSlotUpgrade.java.patch @@ -0,0 +1,23 @@ +--- a/ic2/core/block/invslot/InvSlotUpgrade.java ++++ b/ic2/core/block/invslot/InvSlotUpgrade.java +@@ -17,6 +17,8 @@ + import java.util.List; + import net.minecraft.item.Item; + import net.minecraft.item.ItemStack; ++import ic2.api.upgrade.UpgradableProperty; ++import ic2.core.block.machine.tileentity.TileEntityElectricMachine; + + public class InvSlotUpgrade extends InvSlot { + private static final int maxStackSize = 64; +@@ -89,6 +91,11 @@ + } + } + } ++ } ++ ++ if (iupgradableblock instanceof TileEntityElectricMachine && iupgradableblock.getUpgradableProperties().contains(UpgradableProperty.Transformer)) { ++ TileEntityElectricMachine te = ((TileEntityElectricMachine) iupgradableblock); ++ te.dischargeSlot.setTier(te.dischargeSlot.baseTier + extraTier); + } + + for(TileEntityComponent tileentitycomponent : this.base.getComponents()) { diff --git a/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch new file mode 100644 index 0000000..5f73003 --- /dev/null +++ b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch @@ -0,0 +1,49 @@ +--- a/ic2/core/block/machine/container/ContainerBatchCrafter.java ++++ b/ic2/core/block/machine/container/ContainerBatchCrafter.java +@@ -13,6 +13,8 @@ + import java.util.List; + import net.minecraft.entity.player.EntityPlayer; + import net.minecraft.item.ItemStack; ++import ic2.api.upgrade.IUpgradeItem; ++import net.minecraft.inventory.Slot; + + public class ContainerBatchCrafter extends ContainerElectricMachine { + protected final TIntIntMap indexToSlot = new TIntIntHashMap(); +@@ -41,12 +43,23 @@ + } + + for(int l = 0; l < 4; ++l) { +- this.addSlotToContainer(new SlotInvSlot(tileEntity.upgradeSlot, l, 152, 8 + l * 18)); ++ // Ingredients: 0-8 // Upgrades: 9-12 ++ this.indexToSlot.put(l+9, this.addSlotToContainer(new SlotInvSlot(tileEntity.upgradeSlot, l, 152, 8 + l * 18)).slotNumber); + } + + } + + protected ItemStack handlePlayerSlotShiftClick(EntityPlayer player, ItemStack sourceItemStack) { ++ if (sourceItemStack.getItem() instanceof IUpgradeItem && this.base.upgradeSlot.accepts(sourceItemStack)) { ++ for (int i = 0; i < 4; i++) { ++ Slot slot = this.inventorySlots.get(this.indexToSlot.get(i+9)); ++ if (slot.isItemValid(sourceItemStack)) { ++ sourceItemStack = this.transfer(sourceItemStack, slot); ++ if (StackUtil.isEmpty(sourceItemStack)) return StackUtil.emptyStack; ++ } ++ } ++ } ++ + Tuple.T2, ? extends TIntCollection> t2 = StackUtil.balanceStacks(this.base.ingredients, this.base.acceptPredicate, StackUtil.getSlotsFromInv(this.base.ingredients), Collections.singleton(sourceItemStack)); + TIntIterator tintiterator = t2.b.iterator(); + +@@ -55,7 +68,11 @@ + this.inventorySlots.get(this.indexToSlot.get(i)).onSlotChanged(); + } + +- sourceItemStack = t2.a.isEmpty() ? StackUtil.emptyStack : t2.a.get(0); ++ if (t2.a.isEmpty()) return StackUtil.emptyStack; ++ sourceItemStack = t2.a.get(0); ++ ++ if (this.base.dischargeSlot.accepts(sourceItemStack)) sourceItemStack = this.transfer(sourceItemStack, this.inventorySlots.get(36)); ++ + return sourceItemStack; + } + diff --git a/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch index d558c79..5319900 100644 --- a/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch +++ b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch @@ -1,6 +1,32 @@ --- a/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java +++ b/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java -@@ -297,7 +297,7 @@ +@@ -136,24 +136,7 @@ + int finalI = i; + this.ingredientsRow[i] = new InvSlot(this, "ingredient[" + finalI + ']', InvSlot.Access.I, 1) { + public boolean accepts(ItemStack ingredient) { +- IRecipe irecipe = TileEntityBatchCrafter.this.world.isRemote ? TileEntityBatchCrafter.this.findRecipe() : TileEntityBatchCrafter.this.recipe; +- if (irecipe == null) { +- return false; +- } else { +- assert irecipe.matches(TileEntityBatchCrafter.this.crafting, TileEntityBatchCrafter.this.world); +- +- ItemStack itemstack = TileEntityBatchCrafter.this.craftingGrid[finalI]; +- +- boolean flag; +- try { +- TileEntityBatchCrafter.this.craftingGrid[finalI] = ingredient; +- flag = irecipe.matches(TileEntityBatchCrafter.this.crafting, TileEntityBatchCrafter.this.world); +- } finally { +- TileEntityBatchCrafter.this.craftingGrid[finalI] = itemstack; +- } +- +- return flag; +- } ++ return StackUtil.checkItemEquality(craftingGrid[finalI], ingredient); + } + + public void onChanged() { +@@ -297,7 +280,7 @@ } protected void doCrafting() { diff --git a/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/network/DataEncoder.java.patch b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/network/DataEncoder.java.patch new file mode 100644 index 0000000..808aeec --- /dev/null +++ b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/network/DataEncoder.java.patch @@ -0,0 +1,14 @@ +--- a/ic2/core/network/DataEncoder.java ++++ b/ic2/core/network/DataEncoder.java +@@ -608,6 +608,11 @@ + } else if (dst instanceof TileEntityComponent) { + NBTTagCompound nbttagcompound = (NBTTagCompound)src; + ((TileEntityComponent)dst).readFromNbt(nbttagcompound); ++ } else if (dst.getClass().isArray()) { ++ T[] array1 = (T[]) src; ++ T[] array2 = (T[]) dst; ++ if (array1.length != array2.length) return false; ++ System.arraycopy(array1, 0, array2, 0, array1.length); + } else { + if (!(dst instanceof Collection)) { + return false; diff --git a/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/util/StackUtil.java.patch b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/util/StackUtil.java.patch new file mode 100644 index 0000000..0bc303b --- /dev/null +++ b/projects/IC2-Patched/patches[2.8.164,2.8.165]/minecraft/ic2/core/util/StackUtil.java.patch @@ -0,0 +1,11 @@ +--- a/ic2/core/util/StackUtil.java ++++ b/ic2/core/util/StackUtil.java +@@ -98,7 +98,7 @@ + + public static StackUtil.AdjacentInv getAdjacentInventory(TileEntity source, EnumFacing dir) { + TileEntity tileentity = source.getWorld().getTileEntity(source.getPos().offset(dir)); +- if (!isInventoryTile(tileentity, dir)) { ++ if (!isInventoryTile(tileentity, dir.getOpposite())) { + return null; + } else { + GameProfile gameprofile; diff --git a/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/invslot/InvSlotDischarge.java.patch b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/invslot/InvSlotDischarge.java.patch new file mode 100644 index 0000000..5416be2 --- /dev/null +++ b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/invslot/InvSlotDischarge.java.patch @@ -0,0 +1,18 @@ +--- a/ic2/core/block/invslot/InvSlotDischarge.java ++++ b/ic2/core/block/invslot/InvSlotDischarge.java +@@ -9,6 +9,7 @@ + import net.minecraft.item.ItemStack; + + public class InvSlotDischarge extends InvSlot implements IDischargingSlot { ++ public int baseTier; + public int tier; + public boolean allowRedstoneDust; + +@@ -24,6 +25,7 @@ + super(base, "discharge", access, 1, preferredSide); + this.allowRedstoneDust = true; + this.tier = tier; ++ this.baseTier = tier; + this.allowRedstoneDust = allowRedstoneDust; + } + diff --git a/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/invslot/InvSlotUpgrade.java.patch b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/invslot/InvSlotUpgrade.java.patch new file mode 100644 index 0000000..fa764b6 --- /dev/null +++ b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/invslot/InvSlotUpgrade.java.patch @@ -0,0 +1,23 @@ +--- a/ic2/core/block/invslot/InvSlotUpgrade.java ++++ b/ic2/core/block/invslot/InvSlotUpgrade.java +@@ -18,6 +18,8 @@ + import java.util.List; + import net.minecraft.item.Item; + import net.minecraft.item.ItemStack; ++import ic2.api.upgrade.UpgradableProperty; ++import ic2.core.block.machine.tileentity.TileEntityElectricMachine; + + public class InvSlotUpgrade extends InvSlot { + private static final int maxStackSize = 64; +@@ -90,6 +92,11 @@ + } + } + } ++ } ++ ++ if (iupgradableblock instanceof TileEntityElectricMachine && iupgradableblock.getUpgradableProperties().contains(UpgradableProperty.Transformer)) { ++ TileEntityElectricMachine te = ((TileEntityElectricMachine) iupgradableblock); ++ te.dischargeSlot.setTier(te.dischargeSlot.baseTier + extraTier); + } + + for(TileEntityComponent tileentitycomponent : this.base.getParent().getComponents()) { diff --git a/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch new file mode 100644 index 0000000..5f73003 --- /dev/null +++ b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/machine/container/ContainerBatchCrafter.java.patch @@ -0,0 +1,49 @@ +--- a/ic2/core/block/machine/container/ContainerBatchCrafter.java ++++ b/ic2/core/block/machine/container/ContainerBatchCrafter.java +@@ -13,6 +13,8 @@ + import java.util.List; + import net.minecraft.entity.player.EntityPlayer; + import net.minecraft.item.ItemStack; ++import ic2.api.upgrade.IUpgradeItem; ++import net.minecraft.inventory.Slot; + + public class ContainerBatchCrafter extends ContainerElectricMachine { + protected final TIntIntMap indexToSlot = new TIntIntHashMap(); +@@ -41,12 +43,23 @@ + } + + for(int l = 0; l < 4; ++l) { +- this.addSlotToContainer(new SlotInvSlot(tileEntity.upgradeSlot, l, 152, 8 + l * 18)); ++ // Ingredients: 0-8 // Upgrades: 9-12 ++ this.indexToSlot.put(l+9, this.addSlotToContainer(new SlotInvSlot(tileEntity.upgradeSlot, l, 152, 8 + l * 18)).slotNumber); + } + + } + + protected ItemStack handlePlayerSlotShiftClick(EntityPlayer player, ItemStack sourceItemStack) { ++ if (sourceItemStack.getItem() instanceof IUpgradeItem && this.base.upgradeSlot.accepts(sourceItemStack)) { ++ for (int i = 0; i < 4; i++) { ++ Slot slot = this.inventorySlots.get(this.indexToSlot.get(i+9)); ++ if (slot.isItemValid(sourceItemStack)) { ++ sourceItemStack = this.transfer(sourceItemStack, slot); ++ if (StackUtil.isEmpty(sourceItemStack)) return StackUtil.emptyStack; ++ } ++ } ++ } ++ + Tuple.T2, ? extends TIntCollection> t2 = StackUtil.balanceStacks(this.base.ingredients, this.base.acceptPredicate, StackUtil.getSlotsFromInv(this.base.ingredients), Collections.singleton(sourceItemStack)); + TIntIterator tintiterator = t2.b.iterator(); + +@@ -55,7 +68,11 @@ + this.inventorySlots.get(this.indexToSlot.get(i)).onSlotChanged(); + } + +- sourceItemStack = t2.a.isEmpty() ? StackUtil.emptyStack : t2.a.get(0); ++ if (t2.a.isEmpty()) return StackUtil.emptyStack; ++ sourceItemStack = t2.a.get(0); ++ ++ if (this.base.dischargeSlot.accepts(sourceItemStack)) sourceItemStack = this.transfer(sourceItemStack, this.inventorySlots.get(36)); ++ + return sourceItemStack; + } + diff --git a/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch index dad854b..1d32dbc 100644 --- a/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch +++ b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java.patch @@ -1,6 +1,32 @@ --- a/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java +++ b/ic2/core/block/machine/tileentity/TileEntityBatchCrafter.java -@@ -298,7 +298,7 @@ +@@ -137,24 +137,7 @@ + int finalI = i; + this.ingredientsRow[i] = new InvSlot(this, "ingredient[" + finalI + ']', InvSlot.Access.I, 1) { + public boolean accepts(ItemStack ingredient) { +- IRecipe irecipe = TileEntityBatchCrafter.this.world.isRemote ? TileEntityBatchCrafter.this.findRecipe() : TileEntityBatchCrafter.this.recipe; +- if (irecipe == null) { +- return false; +- } else { +- assert irecipe.matches(TileEntityBatchCrafter.this.crafting, TileEntityBatchCrafter.this.world); +- +- ItemStack itemstack = TileEntityBatchCrafter.this.craftingGrid[finalI]; +- +- boolean flag; +- try { +- TileEntityBatchCrafter.this.craftingGrid[finalI] = ingredient; +- flag = irecipe.matches(TileEntityBatchCrafter.this.crafting, TileEntityBatchCrafter.this.world); +- } finally { +- TileEntityBatchCrafter.this.craftingGrid[finalI] = itemstack; +- } +- +- return flag; +- } ++ return StackUtil.checkItemEquality(craftingGrid[finalI], ingredient); + } + + public void onChanged() { +@@ -298,7 +281,7 @@ } protected void doCrafting() { diff --git a/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/network/DataEncoder.java.patch b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/network/DataEncoder.java.patch new file mode 100644 index 0000000..808aeec --- /dev/null +++ b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/network/DataEncoder.java.patch @@ -0,0 +1,14 @@ +--- a/ic2/core/network/DataEncoder.java ++++ b/ic2/core/network/DataEncoder.java +@@ -608,6 +608,11 @@ + } else if (dst instanceof TileEntityComponent) { + NBTTagCompound nbttagcompound = (NBTTagCompound)src; + ((TileEntityComponent)dst).readFromNbt(nbttagcompound); ++ } else if (dst.getClass().isArray()) { ++ T[] array1 = (T[]) src; ++ T[] array2 = (T[]) dst; ++ if (array1.length != array2.length) return false; ++ System.arraycopy(array1, 0, array2, 0, array1.length); + } else { + if (!(dst instanceof Collection)) { + return false; diff --git a/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/util/StackUtil.java.patch b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/util/StackUtil.java.patch new file mode 100644 index 0000000..0bc303b --- /dev/null +++ b/projects/IC2-Patched/patches[2.8.221,+]/minecraft/ic2/core/util/StackUtil.java.patch @@ -0,0 +1,11 @@ +--- a/ic2/core/util/StackUtil.java ++++ b/ic2/core/util/StackUtil.java +@@ -98,7 +98,7 @@ + + public static StackUtil.AdjacentInv getAdjacentInventory(TileEntity source, EnumFacing dir) { + TileEntity tileentity = source.getWorld().getTileEntity(source.getPos().offset(dir)); +- if (!isInventoryTile(tileentity, dir)) { ++ if (!isInventoryTile(tileentity, dir.getOpposite())) { + return null; + } else { + GameProfile gameprofile; diff --git a/settings.gradle.kts b/settings.gradle.kts index 03f2c4f..4461e83 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,6 +16,10 @@ pluginManagement { name = "FancyGradle" url = uri("https://gitlab.com/api/v4/projects/26758973/packages/maven") } + maven { + name = "Garden of Fancy" + url = uri("https://maven.gofancy.wtf/releases") + } } } diff --git a/src/main/generatedResources/patches/patches[2.8.164,2.8.165]/ic2patches.pack.lzma b/src/main/generatedResources/patches/patches[2.8.164,2.8.165]/ic2patches.pack.lzma index 98a4921..32b923d 100644 Binary files a/src/main/generatedResources/patches/patches[2.8.164,2.8.165]/ic2patches.pack.lzma and b/src/main/generatedResources/patches/patches[2.8.164,2.8.165]/ic2patches.pack.lzma differ diff --git a/src/main/generatedResources/patches/patches[2.8.221,+]/ic2patches.pack.lzma b/src/main/generatedResources/patches/patches[2.8.221,+]/ic2patches.pack.lzma index ee48f08..df17742 100644 Binary files a/src/main/generatedResources/patches/patches[2.8.221,+]/ic2patches.pack.lzma and b/src/main/generatedResources/patches/patches[2.8.221,+]/ic2patches.pack.lzma differ diff --git a/src/main/java/mods/su5ed/ic2patcher/asm/BinPatchManager.java b/src/main/java/mods/su5ed/ic2patcher/asm/BinPatchManager.java index eb82998..6a7f888 100644 --- a/src/main/java/mods/su5ed/ic2patcher/asm/BinPatchManager.java +++ b/src/main/java/mods/su5ed/ic2patcher/asm/BinPatchManager.java @@ -29,7 +29,6 @@ import com.google.common.io.ByteStreams; import com.google.common.io.Files; import mods.su5ed.ic2patcher.util.IC2VersionExtractor; -import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.patcher.ClassPatch; import net.minecraftforge.fml.relauncher.FMLLaunchHandler; import net.minecraftforge.fml.repackage.com.nothome.delta.GDiffPatcher; @@ -155,7 +154,11 @@ public void setup(Map data) { Enumeration entries = zip.entries(); String patches = "ic2patches.pack.lzma"; String versionIC2 = IC2VersionExtractor.getIC2Version(mcLocation); - if (versionIC2 == null) throw new NullPointerException("Couldn't find IC2 Version! Is IC2 installed?"); + if (versionIC2 == null) { + if (!FMLLaunchHandler.isDeobfuscatedEnvironment()) throw new NullPointerException("Couldn't find IC2 Version! Is IC2 installed?"); + LOG.error("Couldn't find IC2 Version, however this is Deobfuscated Environment, so this error will be ignored and no patches will be loaded."); + return; + } if (DEBUG) LOG.debug("Current IC2 version: " + versionIC2); versionIC2 = versionIC2.substring(0, versionIC2.indexOf("-")); diff --git a/src/main/java/mods/su5ed/ic2patcher/util/IC2VersionExtractor.java b/src/main/java/mods/su5ed/ic2patcher/util/IC2VersionExtractor.java index fad15cd..f33beda 100644 --- a/src/main/java/mods/su5ed/ic2patcher/util/IC2VersionExtractor.java +++ b/src/main/java/mods/su5ed/ic2patcher/util/IC2VersionExtractor.java @@ -1,6 +1,8 @@ package mods.su5ed.ic2patcher.util; import com.google.gson.Gson; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.io.*; import java.util.List; @@ -13,6 +15,7 @@ public class IC2VersionExtractor { private static String ic2Version = null; + private static final Logger logger = LogManager.getLogger("IC2-Patcher/IC2VersionExtraction"); /** * Used to get cached IC2 Version extracted from the IC2 Jar. Requires {@link IC2VersionExtractor#getIC2Version(File)} to be called at least once. @@ -27,11 +30,14 @@ public class IC2VersionExtractor { * @throws IOException when IO Exception occurs. */ public static String getIC2Version(File mcLocation) throws IOException { - if (mcLocation == null) return ic2Version; + if (mcLocation == null || ic2Version != null) return ic2Version; File mods = new File(mcLocation, "mods"); - if (!mods.exists() || mods.listFiles() == null) return null; + if (!mods.exists() || mods.listFiles() == null) { + logger.fatal("No mods folder exists or list of files returned is null! This error will cause a crash."); + return null; + } for (File file : mods.listFiles()) { if (!file.exists() || file.isDirectory() || !file.getName().endsWith(".jar")) continue; @@ -44,10 +50,12 @@ public static String getIC2Version(File mcLocation) throws IOException { Map mcModInfo = ((List>)new Gson().fromJson(new InputStreamReader(zip.getInputStream(mcModInfoEntry)), Object.class)).get(0); if (!Objects.equals(mcModInfo.get("modid"), "ic2")) continue; ic2Version = (String) mcModInfo.get("version"); + logger.info("IC2 was found! Extracted version: " + ic2Version); return ic2Version; } catch (Exception ignored) {} } } + logger.fatal("No IC2 was found in the mods folder. Is IC2 Installed? This error will cause a crash."); return null; } }