├── .gitignore ├── LICENSE ├── README.md ├── build ├── build.gradle ├── build.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── resources ├── assets │ └── ccl │ │ └── asm │ │ └── hooks.asm └── ccl_at.cfg └── src └── codechicken └── lib ├── asm ├── ASMBlock.java ├── ASMHelper.java ├── ASMReader.java ├── CCLCorePlugin.java ├── CC_ClassWriter.java ├── ClassHeirachyManager.java ├── ImportantInsnVisitor.java ├── InsnComparator.java ├── InsnListSection.java ├── LocalVariablesSorterVisitor.java ├── ModularASMTransformer.java ├── ObfMapping.java └── RenderHookTransformer.java ├── colour ├── Colour.java ├── ColourARGB.java ├── ColourRGBA.java └── CustomGradient.java ├── config ├── ConfigFile.java ├── ConfigTag.java ├── ConfigTagParent.java ├── DefaultingConfigFile.java └── SimpleProperties.java ├── data ├── MCDataIO.java ├── MCDataInput.java ├── MCDataInputStream.java ├── MCDataOutput.java ├── MCDataOutputStream.java └── MCDataOutputWrapper.java ├── gui └── GuiDraw.java ├── inventory ├── InventoryCopy.java ├── InventoryNBT.java ├── InventoryRange.java ├── InventorySimple.java ├── InventoryUtils.java └── ItemKey.java ├── lighting ├── LC.java ├── LightMatrix.java ├── LightModel.java ├── PlanarLightMatrix.java ├── PlanarLightModel.java └── SimpleBrightnessModel.java ├── math └── MathHelper.java ├── packet ├── ICustomPacketTile.java └── PacketCustom.java ├── raytracer ├── ExtendedMOP.java ├── IndexedCuboid6.java └── RayTracer.java ├── render ├── BlockRenderer.java ├── CCModel.java ├── CCModelLibrary.java ├── CCRenderPipeline.java ├── CCRenderState.java ├── ColourMultiplier.java ├── EntityDigIconFX.java ├── FontUtils.java ├── IFaceRenderer.java ├── IItemRenderer.java ├── ManagedTextureFX.java ├── ModelRegistryHelper.java ├── PlaceholderTexture.java ├── QBImporter.java ├── RenderUtils.java ├── ShaderProgram.java ├── SpriteSheetManager.java ├── TextureDataHolder.java ├── TextureFX.java ├── TextureSpecial.java ├── TextureUtils.java ├── Vertex5.java └── uv │ ├── IconTransformation.java │ ├── MultiIconTransformation.java │ ├── UV.java │ ├── UVRotation.java │ ├── UVScale.java │ ├── UVTransformation.java │ ├── UVTransformationList.java │ └── UVTranslation.java ├── tool ├── LibDownloader.java ├── MCStripTransformer.java ├── Main.java ├── StripClassLoader.java ├── ToolMain.java └── module │ ├── JOptModule.java │ └── ModuleQBConverter.java ├── util ├── Copyable.java └── LangProxy.java ├── vec ├── AxisCycle.java ├── BlockCoord.java ├── Cuboid6.java ├── CuboidCoord.java ├── ITransformation.java ├── IrreversibleTransformationException.java ├── Line3.java ├── Matrix4.java ├── Quat.java ├── Rectangle4i.java ├── RedundantTransformation.java ├── Rotation.java ├── Scale.java ├── SwapYZ.java ├── Transformation.java ├── TransformationList.java ├── Translation.java ├── VariableTransformation.java └── Vector3.java └── world ├── ChunkExtension.java ├── IChunkLoadTile.java ├── TileChunkLoadHook.java ├── WorldExtension.java ├── WorldExtensionInstantiator.java └── WorldExtensionManager.java /.gitignore: -------------------------------------------------------------------------------- 1 | /build/build 2 | /build/.gradle 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CodeChickenLib 2 | ============== 3 | THIS PROJECT IS RETIRED: See [here] for the current repo. 4 | 5 | This is a library of systems to help make various aspects of minecraft modding easier. 6 | It contains libraries for 3D math and transformations, model rendering, packets, config, colours, asm and a few other things. 7 | 8 | Current maven: http://chickenbones.net/maven/ 9 | 10 | Join us on IRC: 11 | - Server: Esper.net 12 | - Channel: #ChickenBones 13 | 14 | 15 | [here]: 16 | -------------------------------------------------------------------------------- /build/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | maven { 5 | name = "forge" 6 | url = "http://files.minecraftforge.net/maven" 7 | } 8 | } 9 | dependencies { 10 | classpath 'net.minecraftforge.gradle:ForgeGradle:2.1-SNAPSHOT' 11 | } 12 | } 13 | 14 | apply plugin: 'net.minecraftforge.gradle.forge' 15 | apply plugin: 'maven' 16 | 17 | group = "codechicken" // http://maven.apache.org/guides/mini/guide-naming-conventions.html 18 | archivesBaseName = "CodeChickenLib" 19 | 20 | // Define properties file 21 | ext.configFile = file "build.properties" 22 | 23 | configFile.withReader { 24 | // Load config. It shall from now be referenced as simply config or project.config 25 | def prop = new Properties() 26 | prop.load(it) 27 | project.ext.config = new ConfigSlurper().parse prop 28 | } 29 | 30 | version = "${project.config.mod_version}." + (System.getenv("BUILD_NUMBER") ?: "1") 31 | 32 | println config.minecraft_version + "-" + config.forge_version 33 | // Setup the forge minecraft plugin data. Specify the preferred forge/minecraft version here 34 | minecraft { 35 | version = config.minecraft_version + "-" + config.forge_version 36 | mappings = config.mappings 37 | runDir = "run" 38 | } 39 | 40 | sourceSets { 41 | main { 42 | def root = project.projectDir.parentFile 43 | java { 44 | srcDir new File(root, "src") 45 | } 46 | resources { 47 | srcDir new File(root, "resources") 48 | } 49 | } 50 | } 51 | 52 | processResources { 53 | // Move access transformer to META-INF 54 | rename '(.+_at.cfg)', 'META-INF/$1' 55 | } 56 | 57 | version = "${project.minecraft.version}-${project.version}" 58 | def commonManifest = { 59 | attributes 'Main-Class': 'codechicken.lib.tool.Main' 60 | attributes 'FMLCorePlugin': 'codechicken.lib.asm.CCLCorePlugin' 61 | attributes 'FMLAT': 'ccl_at.cfg' 62 | } 63 | 64 | jar { 65 | classifier = 'universal' 66 | manifest commonManifest 67 | } 68 | 69 | task devJar(type: Jar) { 70 | from sourceSets.main.output 71 | classifier = 'dev' 72 | manifest commonManifest 73 | } 74 | 75 | // Tell the artifact system about our extra jars 76 | artifacts { 77 | archives devJar 78 | } 79 | 80 | // Configure an upload task. this is setup for uploading to files.minecraftforge.net. There are other examples around 81 | uploadArchives { 82 | dependsOn 'build' 83 | repositories { 84 | if (project.hasProperty("filesmaven")) { 85 | logger.info('Publishing to files server') 86 | 87 | mavenDeployer { 88 | configuration = configurations.deployJars 89 | 90 | repository(url: project.filesmaven.url) { 91 | authentication(userName: project.filesmaven.username, privateKey: project.filesmaven.key) 92 | } 93 | 94 | // This is just the pom data for the maven repo 95 | pom { 96 | groupId = project.group 97 | // Force the maven upload to use the - syntax preferred at files 98 | artifactId = project.archivesBaseName 99 | project { 100 | name project.archivesBaseName 101 | packaging 'jar' 102 | description 'CodeChickenLib' 103 | url 'https://github.com/Chicken-Bones/CodeChickenLib' 104 | 105 | scm { 106 | url 'https://github.com/Chicken-Bones/CodeChickenLib' 107 | connection 'scm:git:git://github.com/Chicken-Bones/CodeChickenLib.git' 108 | developerConnection 'scm:git:git@github.com:Chicken-Bones/CodeChickenLib.git' 109 | } 110 | 111 | issueManagement { 112 | system 'github' 113 | url 'https://github.com/Chicken-Bones/CodeChickenLib/issues' 114 | } 115 | 116 | licenses { 117 | license { 118 | name 'GNU Lesser Public License (GPL), Version 2.1' 119 | url 'https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt' 120 | distribution 'repo' 121 | } 122 | } 123 | 124 | developers { 125 | developer { 126 | id 'chicken-bones' 127 | name 'chicken-bones' 128 | roles { role 'developer' } 129 | } 130 | } 131 | } 132 | } 133 | } 134 | } else { 135 | logger.info('Publishing to repo folder') 136 | 137 | mavenDeployer { 138 | pom.version = "${project.minecraft.version}-${project.version}" 139 | repository(url: 'file://localhost/' + project.file('repo').getAbsolutePath()) 140 | } 141 | } 142 | } 143 | } -------------------------------------------------------------------------------- /build/build.properties: -------------------------------------------------------------------------------- 1 | minecraft_version=1.8.8 2 | forge_version=11.15.0.1650-1.8.8 3 | mappings=snapshot_nodoc_20151225 4 | mod_version=1.1.2 5 | -------------------------------------------------------------------------------- /build/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chicken-Bones/CodeChickenLib/90b840ffbe7b3668fdfa2fd25e44baaa3f641002/build/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /build/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Sep 14 12:28:28 PDT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.7-bin.zip 7 | -------------------------------------------------------------------------------- /build/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /build/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /build/settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This settings file was auto generated by the Gradle buildInit task 3 | * by 'sunstrike' at '21/11/13 14:14' with Gradle 1.9 4 | * 5 | * The settings file is used to specify which projects to include in your build. 6 | * In a single project build this file can be empty or even removed. 7 | * 8 | * Detailed information about configuring a multi-project build in Gradle can be found 9 | * in the user guide at http://gradle.org/docs/1.9/userguide/multi_project_builds.html 10 | */ 11 | 12 | /* 13 | // To declare projects as part of a multi-project build use the 'include' method 14 | include 'shared' 15 | include 'api' 16 | include 'services:webservice' 17 | */ 18 | 19 | rootProject.name = 'CodeChickenLib' 20 | -------------------------------------------------------------------------------- /resources/assets/ccl/asm/hooks.asm: -------------------------------------------------------------------------------- 1 | list n_IItemRenderer 2 | GETSTATIC net/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer.field_147719_a : Lnet/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer; 3 | ALOAD 1 4 | INVOKEVIRTUAL net/minecraft/client/renderer/tileentity/TileEntityItemStackRenderer.func_179022_a (Lnet/minecraft/item/ItemStack;)V 5 | GOTO LEND #end of if statement 6 | 7 | list IItemRenderer 8 | ALOAD 2 9 | INSTANCEOF codechicken/lib/render/IItemRenderer 10 | IFEQ LELSE 11 | ALOAD 2 12 | ALOAD 1 13 | INVOKEINTERFACE codechicken/lib/render/IItemRenderer.renderItem (Lnet/minecraft/item/ItemStack;)V 14 | GOTO LEND 15 | LELSE -------------------------------------------------------------------------------- /resources/ccl_at.cfg: -------------------------------------------------------------------------------- 1 | # CodeChickenLib Access Transformer 2 | public net.minecraft.world.chunk.Chunk field_150816_i #chunkTileEntityMap 3 | public net.minecraft.world.chunk.Chunk field_76636_d #isChunkLoaded 4 | public net.minecraft.server.management.PlayerManager func_72690_a(IIZ)Lnet/minecraft/server/management/PlayerManager$PlayerInstance; #getOrCreateChunkWatcher 5 | public net.minecraft.server.management.PlayerManager$PlayerInstance 6 | public net.minecraft.server.management.PlayerManager$PlayerInstance func_151251_a(Lnet/minecraft/network/Packet;)V #sendToAllPlayersWatchingChunk 7 | public net.minecraft.server.management.PlayerManager$PlayerInstance field_73263_b #playersWatchingChunk 8 | -------------------------------------------------------------------------------- /src/codechicken/lib/asm/ASMBlock.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.asm; 2 | 3 | import com.google.common.collect.BiMap; 4 | import com.google.common.collect.HashBiMap; 5 | import com.google.common.collect.ImmutableMap; 6 | import org.objectweb.asm.tree.AbstractInsnNode; 7 | import org.objectweb.asm.tree.InsnList; 8 | import org.objectweb.asm.tree.JumpInsnNode; 9 | import org.objectweb.asm.tree.LabelNode; 10 | 11 | import java.util.*; 12 | import java.util.Map.Entry; 13 | 14 | import static org.objectweb.asm.tree.AbstractInsnNode.*; 15 | 16 | public class ASMBlock 17 | { 18 | public InsnListSection list; 19 | private BiMap labels; 20 | 21 | public ASMBlock(InsnListSection list, BiMap labels) { 22 | this.list = list; 23 | this.labels = labels; 24 | } 25 | 26 | public ASMBlock(InsnListSection list) { 27 | this(list, HashBiMap.create()); 28 | } 29 | 30 | public ASMBlock(InsnList list) { 31 | this(new InsnListSection(list)); 32 | } 33 | 34 | public ASMBlock() { 35 | this(new InsnListSection()); 36 | } 37 | 38 | public LabelNode getOrAdd(String s) { 39 | LabelNode l = get(s); 40 | if (l == null) 41 | labels.put(s, l = new LabelNode()); 42 | return l; 43 | } 44 | 45 | public LabelNode get(String s) { 46 | return labels.get(s); 47 | } 48 | 49 | public void replaceLabels(Map labelMap, Set usedLabels) { 50 | for (AbstractInsnNode insn : list) 51 | switch (insn.getType()) { 52 | case LABEL: 53 | AbstractInsnNode insn2 = insn.clone(labelMap); 54 | if (insn2 == insn)//identity mapping 55 | continue; 56 | if (usedLabels.contains(insn2)) 57 | throw new IllegalStateException("LabelNode cannot be a part of two InsnLists"); 58 | list.replace(insn, insn2); 59 | break; 60 | case JUMP_INSN: 61 | case FRAME: 62 | case LOOKUPSWITCH_INSN: 63 | case TABLESWITCH_INSN: 64 | list.replace(insn, insn.clone(labelMap)); 65 | } 66 | 67 | for(Entry entry : labelMap.entrySet()) { 68 | String key = labels.inverse().get(entry.getKey()); 69 | if(key != null) 70 | labels.put(key, entry.getValue()); 71 | } 72 | } 73 | 74 | public void replaceLabels(Map labelMap) { 75 | replaceLabels(labelMap, Collections.EMPTY_SET); 76 | } 77 | 78 | public void replaceLabel(String s, LabelNode l) { 79 | LabelNode old = get(s); 80 | if (old != null) 81 | replaceLabels(ImmutableMap.of(old, l)); 82 | } 83 | 84 | /** 85 | * Pulls all common labels from other into this 86 | * @return this 87 | */ 88 | public ASMBlock mergeLabels(ASMBlock other) { 89 | if(labels.isEmpty() || other.labels.isEmpty()) 90 | return this; 91 | 92 | //common labels, give them our nodes 93 | HashMap labelMap = list.identityLabelMap(); 94 | for(Entry entry : other.labels.entrySet()) { 95 | LabelNode old = labels.get(entry.getKey()); 96 | if(old != null) 97 | labelMap.put(old, entry.getValue()); 98 | } 99 | HashSet usedLabels = new HashSet(); 100 | for (AbstractInsnNode insn = other.list.list.getFirst(); insn != null; insn = insn.getNext()) 101 | if(insn.getType() == LABEL) 102 | usedLabels.add((LabelNode) insn); 103 | 104 | replaceLabels(labelMap, usedLabels); 105 | return this; 106 | } 107 | 108 | /** 109 | * Like mergeLabels but pulls insns from other list into this so LabelNodes can be transferred 110 | * @return this 111 | */ 112 | public ASMBlock pullLabels(ASMBlock other) { 113 | other.list.remove(); 114 | return mergeLabels(other); 115 | } 116 | 117 | public ASMBlock copy() { 118 | BiMap labels = HashBiMap.create(); 119 | Map labelMap = list.cloneLabels(); 120 | 121 | for(Entry entry : this.labels.entrySet()) 122 | labels.put(entry.getKey(), labelMap.get(entry.getValue())); 123 | 124 | return new ASMBlock(list.copy(labelMap), labels); 125 | } 126 | 127 | public ASMBlock applyLabels(InsnListSection list2) { 128 | if(labels.isEmpty()) 129 | return new ASMBlock(list2); 130 | 131 | Set cFlowLabels1 = labels.values(); 132 | Set cFlowLabels2 = InsnComparator.getControlFlowLabels(list2); 133 | ASMBlock block = new ASMBlock(list2); 134 | 135 | HashMap labelMap = new HashMap(); 136 | 137 | for(int i = 0, k = 0; i < list.size() && k < list2.size(); ) { 138 | AbstractInsnNode insn1 = list.get(i); 139 | if(!InsnComparator.insnImportant(insn1, cFlowLabels1)) { 140 | i++; 141 | continue; 142 | } 143 | 144 | AbstractInsnNode insn2 = list2.get(k); 145 | if(!InsnComparator.insnImportant(insn2, cFlowLabels2)) { 146 | k++; 147 | continue; 148 | } 149 | 150 | if(insn1.getOpcode() != insn2.getOpcode()) 151 | throw new IllegalArgumentException("Lists do not match:\n"+list+"\n\n"+list2); 152 | 153 | switch(insn1.getType()) { 154 | case LABEL: 155 | labelMap.put((LabelNode) insn1, (LabelNode) insn2); 156 | break; 157 | case JUMP_INSN: 158 | labelMap.put(((JumpInsnNode) insn1).label, ((JumpInsnNode) insn2).label); 159 | break; 160 | } 161 | i++; k++; 162 | } 163 | 164 | for(Entry entry : labels.entrySet()) 165 | block.labels.put(entry.getKey(), labelMap.get(entry.getValue())); 166 | 167 | return block; 168 | } 169 | 170 | public InsnList rawListCopy() { 171 | return list.copy().list; 172 | } 173 | } -------------------------------------------------------------------------------- /src/codechicken/lib/asm/CCLCorePlugin.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.asm; 2 | 3 | import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; 4 | import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; 5 | 6 | import java.util.Map; 7 | 8 | @TransformerExclusions({"codechicken.lib.asm", "codechicken.lib.config"}) 9 | public class CCLCorePlugin implements IFMLLoadingPlugin 10 | { 11 | @Override 12 | public String[] getASMTransformerClass() { 13 | return new String[] { 14 | "codechicken.lib.asm.ClassHeirachyManager", 15 | "codechicken.lib.asm.RenderHookTransformer" 16 | }; 17 | } 18 | 19 | @Override 20 | public String getModContainerClass() { 21 | return null; 22 | } 23 | 24 | @Override 25 | public String getSetupClass() { 26 | return null; 27 | } 28 | 29 | @Override 30 | public void injectData(Map data) { 31 | 32 | } 33 | 34 | @Override 35 | public String getAccessTransformerClass() { 36 | return null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/codechicken/lib/asm/CC_ClassWriter.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.asm; 2 | 3 | import org.objectweb.asm.ClassWriter; 4 | 5 | 6 | public class CC_ClassWriter extends ClassWriter 7 | { 8 | private final boolean runtime; 9 | 10 | public CC_ClassWriter(int flags) { 11 | this(flags, false); 12 | } 13 | 14 | public CC_ClassWriter(int flags, boolean runtime) { 15 | super(flags); 16 | this.runtime = runtime; 17 | } 18 | 19 | @Override 20 | protected String getCommonSuperClass(String type1, String type2) { 21 | String c = type1.replace('/', '.'); 22 | String d = type2.replace('/', '.'); 23 | if (ClassHeirachyManager.classExtends(d, c)) 24 | return type1; 25 | if (ClassHeirachyManager.classExtends(c, d)) 26 | return type2; 27 | do 28 | c = ClassHeirachyManager.getSuperClass(c, runtime); 29 | while (!ClassHeirachyManager.classExtends(d, c)); 30 | 31 | return c.replace('.', '/'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/codechicken/lib/asm/ClassHeirachyManager.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.asm; 2 | 3 | import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; 4 | import net.minecraft.launchwrapper.IClassTransformer; 5 | import net.minecraft.launchwrapper.Launch; 6 | import net.minecraft.launchwrapper.LaunchClassLoader; 7 | import org.objectweb.asm.tree.ClassNode; 8 | 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.HashSet; 12 | 13 | /** 14 | * This is added as a class transformer if CodeChickenCore is installed. Adding it as a class transformer will speed evaluation up slightly by automatically caching superclasses when they are first loaded. 15 | */ 16 | public class ClassHeirachyManager implements IClassTransformer 17 | { 18 | public static class SuperCache 19 | { 20 | String superclass; 21 | public HashSet parents = new HashSet(); 22 | private boolean flattened; 23 | 24 | public void add(String parent) { 25 | parents.add(parent); 26 | } 27 | 28 | public void flatten() { 29 | if (flattened) 30 | return; 31 | 32 | for (String s : new ArrayList(parents)) { 33 | SuperCache c = declareClass(s); 34 | if (c != null) { 35 | c.flatten(); 36 | parents.addAll(c.parents); 37 | } 38 | } 39 | flattened = true; 40 | } 41 | } 42 | 43 | public static HashMap superclasses = new HashMap(); 44 | private static LaunchClassLoader cl = Launch.classLoader; 45 | 46 | public static String toKey(String name) { 47 | if (ObfMapping.obfuscated) 48 | name = FMLDeobfuscatingRemapper.INSTANCE.map(name.replace('.', '/')).replace('/', '.'); 49 | return name; 50 | } 51 | 52 | public static String unKey(String name) { 53 | if (ObfMapping.obfuscated) 54 | name = FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/', '.'); 55 | return name; 56 | } 57 | 58 | /** 59 | * @param name The class in question 60 | * @param superclass The class being extended 61 | * @return true if clazz extends, either directly or indirectly, superclass. 62 | */ 63 | public static boolean classExtends(String name, String superclass) { 64 | name = toKey(name); 65 | superclass = toKey(superclass); 66 | 67 | if (name.equals(superclass)) 68 | return true; 69 | 70 | SuperCache cache = declareClass(name); 71 | if (cache == null)//just can't handle this 72 | return false; 73 | 74 | cache.flatten(); 75 | return cache.parents.contains(superclass); 76 | } 77 | 78 | private static SuperCache declareClass(String name) { 79 | name = toKey(name); 80 | SuperCache cache = superclasses.get(name); 81 | 82 | if (cache != null) 83 | return cache; 84 | 85 | try { 86 | byte[] bytes = cl.getClassBytes(unKey(name)); 87 | if (bytes != null) 88 | cache = declareASM(bytes); 89 | } catch (Exception e) { 90 | } 91 | 92 | if (cache != null) 93 | return cache; 94 | 95 | 96 | try { 97 | cache = declareReflection(name); 98 | } catch (ClassNotFoundException e) { 99 | } 100 | 101 | return cache; 102 | } 103 | 104 | private static SuperCache declareReflection(String name) throws ClassNotFoundException { 105 | Class aclass = Class.forName(name); 106 | 107 | SuperCache cache = getOrCreateCache(name); 108 | if (aclass.isInterface()) 109 | cache.superclass = "java.lang.Object"; 110 | else if (name.equals("java.lang.Object")) 111 | return cache; 112 | else 113 | cache.superclass = toKey(aclass.getSuperclass().getName()); 114 | 115 | cache.add(cache.superclass); 116 | for (Class iclass : aclass.getInterfaces()) 117 | cache.add(toKey(iclass.getName())); 118 | 119 | return cache; 120 | } 121 | 122 | private static SuperCache declareASM(byte[] bytes) { 123 | ClassNode node = ASMHelper.createClassNode(bytes); 124 | String name = toKey(node.name); 125 | 126 | SuperCache cache = getOrCreateCache(name); 127 | cache.superclass = toKey(node.superName.replace('/', '.')); 128 | cache.add(cache.superclass); 129 | for (String iclass : node.interfaces) 130 | cache.add(toKey(iclass.replace('/', '.'))); 131 | 132 | return cache; 133 | } 134 | 135 | @Override 136 | public byte[] transform(String name, String tname, byte[] bytes) { 137 | if (bytes == null) 138 | return null; 139 | 140 | if (!superclasses.containsKey(tname)) 141 | declareASM(bytes); 142 | 143 | return bytes; 144 | } 145 | 146 | public static SuperCache getOrCreateCache(String name) { 147 | SuperCache cache = superclasses.get(name); 148 | if (cache == null) 149 | superclasses.put(name, cache = new SuperCache()); 150 | return cache; 151 | } 152 | 153 | public static String getSuperClass(String name, boolean runtime) { 154 | name = toKey(name); 155 | SuperCache cache = declareClass(name); 156 | if (cache == null) 157 | return "java.lang.Object"; 158 | 159 | cache.flatten(); 160 | String s = cache.superclass; 161 | if (!runtime) 162 | s = FMLDeobfuscatingRemapper.INSTANCE.unmap(s); 163 | return s; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/codechicken/lib/asm/ImportantInsnVisitor.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.asm; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | import org.objectweb.asm.tree.MethodNode; 7 | 8 | public class ImportantInsnVisitor extends ClassVisitor 9 | { 10 | public class ImportantInsnMethodVisitor extends MethodVisitor 11 | { 12 | MethodVisitor delegate; 13 | 14 | public ImportantInsnMethodVisitor(int access, String name, String desc, String signature, String[] exceptions) { 15 | super(Opcodes.ASM4, new MethodNode(access, name, desc, signature, exceptions)); 16 | delegate = cv.visitMethod(access, name, desc, signature, exceptions); 17 | } 18 | 19 | @Override 20 | public void visitEnd() { 21 | super.visitEnd(); 22 | MethodNode mnode = (MethodNode)mv; 23 | mnode.instructions = InsnComparator.getImportantList(mnode.instructions); 24 | mnode.accept(delegate); 25 | } 26 | } 27 | 28 | public ImportantInsnVisitor(ClassVisitor cv) { 29 | super(Opcodes.ASM4, cv); 30 | } 31 | 32 | @Override 33 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 34 | return new ImportantInsnMethodVisitor(access, name, desc, signature, exceptions); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/codechicken/lib/asm/LocalVariablesSorterVisitor.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.asm; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | import org.objectweb.asm.commons.LocalVariablesSorter; 7 | 8 | import java.util.Set; 9 | 10 | public class LocalVariablesSorterVisitor extends ClassVisitor 11 | { 12 | public Set methods; 13 | public String owner; 14 | 15 | public LocalVariablesSorterVisitor(Set methods, ClassVisitor cv) { 16 | super(Opcodes.ASM4, cv); 17 | this.methods = methods; 18 | } 19 | 20 | public LocalVariablesSorterVisitor(ClassVisitor cv) { 21 | this(null, cv); 22 | } 23 | 24 | @Override 25 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 26 | super.visit(version, access, name, signature, superName, interfaces); 27 | owner = name; 28 | } 29 | 30 | @Override 31 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 32 | MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); 33 | return methods == null || methods.contains(new ObfMapping(owner, name, desc)) ? new LocalVariablesSorter(access, desc, mv) : mv; 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/codechicken/lib/asm/RenderHookTransformer.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.asm; 2 | 3 | import codechicken.lib.asm.ModularASMTransformer.MethodInjector; 4 | import net.minecraft.launchwrapper.IClassTransformer; 5 | 6 | import java.util.Map; 7 | 8 | public class RenderHookTransformer implements IClassTransformer 9 | { 10 | private ModularASMTransformer transformer = new ModularASMTransformer(); 11 | 12 | public RenderHookTransformer() { 13 | Map blocks = ASMReader.loadResource("/assets/ccl/asm/hooks.asm"); 14 | transformer.add(new MethodInjector(new ObfMapping("net/minecraft/client/renderer/entity/RenderItem", 15 | "func_180454_a", "(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/resources/model/IBakedModel;)V"), 16 | blocks.get("n_IItemRenderer"), blocks.get("IItemRenderer"), true)); 17 | } 18 | 19 | @Override 20 | public byte[] transform(String name, String tname, byte[] bytes) { 21 | return transformer.transform(name, bytes); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/codechicken/lib/colour/Colour.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.colour; 2 | 3 | import codechicken.lib.config.ConfigTag.IConfigType; 4 | import codechicken.lib.math.MathHelper; 5 | import codechicken.lib.util.Copyable; 6 | import net.minecraft.client.renderer.GlStateManager; 7 | import net.minecraftforge.fml.relauncher.Side; 8 | import net.minecraftforge.fml.relauncher.SideOnly; 9 | 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | public abstract class Colour implements Copyable 14 | { 15 | public static IConfigType configRGB = new IConfigType() 16 | { 17 | @Override 18 | public String configValue(Colour entry) { 19 | String s = Long.toString(((long) entry.rgb()) << 32 >>> 32, 16); 20 | while (s.length() < 6) 21 | s = "0" + s; 22 | return "0x" + s.toUpperCase(); 23 | } 24 | 25 | private final Pattern patternRGB = Pattern.compile("(\\d+),(\\d+),(\\d+)"); 26 | 27 | @Override 28 | public Colour valueOf(String text) throws Exception { 29 | Matcher matcherRGB = patternRGB.matcher(text.replaceAll("\\s", "")); 30 | if (matcherRGB.matches()) 31 | return new ColourRGBA( 32 | Integer.parseInt(matcherRGB.group(1)), 33 | Integer.parseInt(matcherRGB.group(2)), 34 | Integer.parseInt(matcherRGB.group(3)), 35 | 0xFF); 36 | 37 | int hex = (int) Long.parseLong(text.replace("0x", ""), 16); 38 | return new ColourRGBA(hex << 8 | 0xFF); 39 | } 40 | }; 41 | 42 | public byte r; 43 | public byte g; 44 | public byte b; 45 | public byte a; 46 | 47 | public Colour(int r, int g, int b, int a) { 48 | this.r = (byte) r; 49 | this.g = (byte) g; 50 | this.b = (byte) b; 51 | this.a = (byte) a; 52 | } 53 | 54 | public Colour(Colour colour) { 55 | r = colour.r; 56 | g = colour.g; 57 | b = colour.b; 58 | a = colour.a; 59 | } 60 | 61 | @SideOnly(Side.CLIENT) 62 | public void glColour() { 63 | GlStateManager.color((r & 0xFF) / 255F, (g & 0xFF) / 255F, (b & 0xFF) / 255F, (a & 0xFF) / 255F); 64 | } 65 | 66 | @SideOnly(Side.CLIENT) 67 | public void glColour(int a) { 68 | GlStateManager.color((r & 0xFF) / 255F, (g & 0xFF) / 255F, (b & 0xFF) / 255F, a / 255F); 69 | } 70 | 71 | public abstract int pack(); 72 | 73 | @Override 74 | public String toString() { 75 | return getClass().getSimpleName() + "[0x" + Integer.toHexString(pack()).toUpperCase() + "]"; 76 | } 77 | 78 | public Colour add(Colour colour2) { 79 | a += colour2.a; 80 | r += colour2.r; 81 | g += colour2.g; 82 | b += colour2.b; 83 | return this; 84 | } 85 | 86 | public Colour sub(Colour colour2) { 87 | int ia = (a & 0xFF) - (colour2.a & 0xFF); 88 | int ir = (r & 0xFF) - (colour2.r & 0xFF); 89 | int ig = (g & 0xFF) - (colour2.g & 0xFF); 90 | int ib = (b & 0xFF) - (colour2.b & 0xFF); 91 | a = (byte) (ia < 0 ? 0 : ia); 92 | r = (byte) (ir < 0 ? 0 : ir); 93 | g = (byte) (ig < 0 ? 0 : ig); 94 | b = (byte) (ib < 0 ? 0 : ib); 95 | return this; 96 | } 97 | 98 | public Colour invert() { 99 | a = (byte) (0xFF - (a & 0xFF)); 100 | r = (byte) (0xFF - (r & 0xFF)); 101 | g = (byte) (0xFF - (g & 0xFF)); 102 | b = (byte) (0xFF - (b & 0xFF)); 103 | return this; 104 | } 105 | 106 | public Colour multiply(Colour colour2) { 107 | a = (byte) ((a & 0xFF) * ((colour2.a & 0xFF) / 255D)); 108 | r = (byte) ((r & 0xFF) * ((colour2.r & 0xFF) / 255D)); 109 | g = (byte) ((g & 0xFF) * ((colour2.g & 0xFF) / 255D)); 110 | b = (byte) ((b & 0xFF) * ((colour2.b & 0xFF) / 255D)); 111 | return this; 112 | } 113 | 114 | public Colour scale(double d) { 115 | a = (byte) ((a & 0xFF) * d); 116 | r = (byte) ((r & 0xFF) * d); 117 | g = (byte) ((g & 0xFF) * d); 118 | b = (byte) ((b & 0xFF) * d); 119 | return this; 120 | } 121 | 122 | public Colour interpolate(Colour colour2, double d) { 123 | return this.add(colour2.copy().sub(this).scale(d)); 124 | } 125 | 126 | public Colour multiplyC(double d) { 127 | r = (byte) MathHelper.clip((r & 0xFF) * d, 0, 255); 128 | g = (byte) MathHelper.clip((g & 0xFF) * d, 0, 255); 129 | b = (byte) MathHelper.clip((b & 0xFF) * d, 0, 255); 130 | 131 | return this; 132 | } 133 | 134 | public abstract Colour copy(); 135 | 136 | public int rgb() { 137 | return (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF); 138 | } 139 | 140 | public int argb() { 141 | return (a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF); 142 | } 143 | 144 | public int rgba() { 145 | return (r & 0xFF) << 24 | (g & 0xFF) << 16 | (b & 0xFF) << 8 | (a & 0xFF); 146 | } 147 | 148 | public Colour set(Colour colour) { 149 | r = colour.r; 150 | g = colour.g; 151 | b = colour.b; 152 | a = colour.a; 153 | return this; 154 | } 155 | 156 | public boolean equals(Colour colour) { 157 | return colour != null && rgba() == colour.rgba(); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/codechicken/lib/colour/ColourARGB.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.colour; 2 | 3 | public class ColourARGB extends Colour 4 | { 5 | public ColourARGB(int colour) 6 | { 7 | super((colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF, (colour >> 24) & 0xFF); 8 | } 9 | 10 | public ColourARGB(int a, int r, int g, int b) 11 | { 12 | super(r, g, b, a); 13 | } 14 | 15 | public ColourARGB(ColourARGB colour) 16 | { 17 | super(colour); 18 | } 19 | 20 | public ColourARGB copy() 21 | { 22 | return new ColourARGB(this); 23 | } 24 | 25 | public int pack() 26 | { 27 | return pack(this); 28 | } 29 | 30 | public static int pack(Colour colour) 31 | { 32 | return (colour.a&0xFF) << 24 | (colour.r&0xFF) << 16 | (colour.g&0xFF) << 8 | (colour.b&0xFF); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/codechicken/lib/colour/ColourRGBA.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.colour; 2 | 3 | public class ColourRGBA extends Colour { 4 | public ColourRGBA(int colour) { 5 | super((colour >> 24) & 0xFF, (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF); 6 | } 7 | 8 | public ColourRGBA(double r, double g, double b, double a) { 9 | super((int) (255 * r), (int) (255 * g), (int) (255 * b), (int) (255 * a)); 10 | } 11 | 12 | public ColourRGBA(int r, int g, int b, int a) { 13 | super(r, g, b, a); 14 | } 15 | 16 | public ColourRGBA(ColourRGBA colour) { 17 | super(colour); 18 | } 19 | 20 | public int pack() { 21 | return pack(this); 22 | } 23 | 24 | @Override 25 | public Colour copy() { 26 | return new ColourRGBA(this); 27 | } 28 | 29 | public static int pack(Colour colour) { 30 | return (colour.r & 0xFF) << 24 | (colour.g & 0xFF) << 16 | (colour.b & 0xFF) << 8 | (colour.a & 0xFF); 31 | } 32 | 33 | public static int multiply(int c1, int c2) { 34 | if(c1 == -1) return c2; 35 | if(c2 == -1) return c1; 36 | int r = (((c1 >>> 24) * (c2 >>> 24)) & 0xFF00) << 16; 37 | int g = (((c1 >> 16 & 0xFF) * (c2 >> 16 & 0xFF)) & 0xFF00) << 8; 38 | int b = ((c1 >> 8 & 0xFF) * (c2 >> 8 & 0xFF)) & 0xFF00; 39 | int a = ((c1 & 0xFF) * (c2 & 0xFF)) >> 8; 40 | return r|g|b|a; 41 | } 42 | 43 | public static int multiplyC(int c, float f) { 44 | int r = (int) ((c >>> 24) * f); 45 | int g = (int) ((c >> 16 & 0xFF) * f); 46 | int b = (int) ((c >> 8 & 0xFF) * f); 47 | return r<<24 | g<<16 | b<<8 | c&0xFF; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/codechicken/lib/colour/CustomGradient.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.colour; 2 | 3 | import codechicken.lib.math.MathHelper; 4 | import codechicken.lib.render.TextureUtils; 5 | import net.minecraft.util.ResourceLocation; 6 | 7 | import java.awt.image.BufferedImage; 8 | 9 | public class CustomGradient 10 | { 11 | public int[] gradient; 12 | 13 | public CustomGradient(ResourceLocation textureFile) 14 | { 15 | BufferedImage img = TextureUtils.loadBufferedImage(textureFile); 16 | if(img == null) 17 | throw new RuntimeException("File not found: "+textureFile.toString()); 18 | 19 | int[] data = new int[img.getWidth()]; 20 | img.getRGB(0, 0, img.getWidth(), 1, data, 0, img.getWidth()); 21 | gradient = new int[img.getWidth()]; 22 | for(int i = 0; i < data.length; i++) 23 | gradient[i] = (data[i]<<8)|(((data[i])>>24)&0xFF); 24 | } 25 | 26 | public ColourRGBA getColour(double position) 27 | { 28 | return new ColourRGBA(getColourI(position)); 29 | } 30 | 31 | public int getColourI(double position) 32 | { 33 | int off = (int)MathHelper.clip(gradient.length*position, 0, gradient.length-1); 34 | return gradient[off]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/codechicken/lib/config/ConfigFile.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.config; 2 | 3 | import java.io.*; 4 | 5 | public class ConfigFile extends ConfigTagParent 6 | { 7 | public static final byte[] crlf = new byte[]{0xD, 0xA}; 8 | 9 | public File file; 10 | private boolean loading; 11 | 12 | public ConfigFile(File file) { 13 | newlinemode = 2; 14 | load(file); 15 | } 16 | 17 | protected ConfigFile() {} 18 | 19 | protected void load(File file) { 20 | try { 21 | if(!file.getParentFile().exists()) 22 | file.getParentFile().mkdirs(); 23 | if (!file.exists()) 24 | file.createNewFile(); 25 | } catch (IOException e) { 26 | throw new RuntimeException(e); 27 | } 28 | this.file = file; 29 | loadConfig(); 30 | } 31 | 32 | protected void loadConfig() { 33 | loading = true; 34 | BufferedReader reader; 35 | try { 36 | reader = new BufferedReader(new FileReader(file)); 37 | 38 | while (true) { 39 | reader.mark(2000); 40 | String line = reader.readLine(); 41 | if (line != null && line.startsWith("#")) { 42 | if (comment == null || comment.equals("")) 43 | comment = line.substring(1); 44 | else 45 | comment = comment + "\n" + line.substring(1); 46 | } else { 47 | reader.reset(); 48 | break; 49 | } 50 | } 51 | loadChildren(reader); 52 | reader.close(); 53 | 54 | } catch (IOException e) { 55 | throw new RuntimeException(e); 56 | } 57 | 58 | loading = false; 59 | } 60 | 61 | @Override 62 | public ConfigFile setComment(String header) { 63 | super.setComment(header); 64 | return this; 65 | } 66 | 67 | @Override 68 | public ConfigFile setSortMode(int mode) { 69 | super.setSortMode(mode); 70 | return this; 71 | } 72 | 73 | @Override 74 | public String getNameQualifier() { 75 | return ""; 76 | } 77 | 78 | public static String readLine(BufferedReader reader) throws IOException { 79 | String line = reader.readLine(); 80 | return line == null ? null : line.replace("\t", ""); 81 | } 82 | 83 | public static void writeLine(PrintWriter writer, String line, int tabs) { 84 | for (int i = 0; i < tabs; i++) 85 | writer.print('\t'); 86 | 87 | writer.println(line); 88 | } 89 | 90 | public void saveConfig() { 91 | if (loading) 92 | return; 93 | 94 | PrintWriter writer; 95 | try { 96 | writer = new PrintWriter(file); 97 | } catch (FileNotFoundException e) { 98 | throw new RuntimeException(e); 99 | } 100 | 101 | writeComment(writer, 0); 102 | ConfigFile.writeLine(writer, "", 0); 103 | saveTagTree(writer, 0, ""); 104 | writer.flush(); 105 | writer.close(); 106 | } 107 | 108 | public boolean isLoading() { 109 | return loading; 110 | } 111 | } -------------------------------------------------------------------------------- /src/codechicken/lib/config/DefaultingConfigFile.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.config; 2 | 3 | import java.io.File; 4 | 5 | public class DefaultingConfigFile extends ConfigFile 6 | { 7 | public DefaultingConfigFile(File file) { 8 | super(); 9 | if(file.exists()) 10 | load(file); 11 | } 12 | 13 | @Override 14 | public void saveConfig() { 15 | if(file != null) 16 | super.saveConfig(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/codechicken/lib/config/SimpleProperties.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.config; 2 | 3 | import java.io.*; 4 | import java.nio.charset.Charset; 5 | import java.util.HashMap; 6 | import java.util.Map.Entry; 7 | 8 | public class SimpleProperties 9 | { 10 | public HashMap propertyMap = new HashMap(); 11 | public File propertyFile; 12 | public boolean saveOnChange = false; 13 | public String encoding; 14 | 15 | private boolean loading = false; 16 | 17 | public SimpleProperties(File file, boolean saveOnChange, String encoding) 18 | { 19 | propertyFile = file; 20 | this.saveOnChange = saveOnChange; 21 | this.encoding = encoding; 22 | } 23 | 24 | public SimpleProperties(File file, boolean saveOnChange) 25 | { 26 | this(file, saveOnChange, Charset.defaultCharset().name()); 27 | } 28 | 29 | public SimpleProperties(File file) 30 | { 31 | this(file, true); 32 | } 33 | 34 | public void load() 35 | { 36 | clear(); 37 | loading = true; 38 | 39 | try 40 | { 41 | BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(propertyFile), encoding)); 42 | while(true) 43 | { 44 | String read = reader.readLine(); 45 | if(read == null) 46 | break; 47 | 48 | int equalIndex = read.indexOf('='); 49 | if(equalIndex == -1) 50 | continue; 51 | 52 | setProperty(read.substring(0, equalIndex), read.substring(equalIndex+1)); 53 | } 54 | reader.close(); 55 | } 56 | catch(Exception e) 57 | { 58 | throw new RuntimeException(e); 59 | } 60 | loading = false; 61 | } 62 | 63 | public void save() 64 | { 65 | try 66 | { 67 | PrintStream writer = new PrintStream(propertyFile); 68 | 69 | for(Entry entry : propertyMap.entrySet()) 70 | { 71 | writer.println(entry.getKey()+"="+entry.getValue()); 72 | } 73 | 74 | writer.close(); 75 | } 76 | catch(Exception e) 77 | { 78 | throw new RuntimeException(e); 79 | } 80 | } 81 | 82 | public void clear() 83 | { 84 | propertyMap.clear(); 85 | } 86 | 87 | public boolean hasProperty(String key) 88 | { 89 | return propertyMap.containsKey(key); 90 | } 91 | 92 | public void removeProperty(String key) 93 | { 94 | if(propertyMap.remove(key) != null && saveOnChange && !loading) 95 | save(); 96 | } 97 | 98 | public void setProperty(String key, int value) 99 | { 100 | setProperty(key, Integer.toString(value)); 101 | } 102 | 103 | public void setProperty(String key, boolean value) 104 | { 105 | setProperty(key, Boolean.toString(value)); 106 | } 107 | 108 | public void setProperty(String key, String value) 109 | { 110 | propertyMap.put(key, value); 111 | if(saveOnChange && !loading) 112 | save(); 113 | } 114 | 115 | public int getProperty(String property, int defaultvalue) 116 | { 117 | try { 118 | return Integer.parseInt(getProperty(property, Integer.toString(defaultvalue))); 119 | } catch(NumberFormatException nfe) 120 | {return defaultvalue;} 121 | } 122 | 123 | public boolean getProperty(String property, boolean defaultvalue) 124 | { 125 | try { 126 | return Boolean.parseBoolean(getProperty(property, Boolean.toString(defaultvalue))); 127 | } catch(NumberFormatException nfe) 128 | {return defaultvalue;} 129 | } 130 | 131 | public String getProperty(String property, String defaultvalue) 132 | { 133 | String value = propertyMap.get(property); 134 | if(value == null) 135 | { 136 | setProperty(property, defaultvalue); 137 | return defaultvalue; 138 | } 139 | return value; 140 | } 141 | 142 | public String getProperty(String property) 143 | { 144 | return propertyMap.get(property); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/codechicken/lib/data/MCDataIO.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.data; 2 | 3 | import com.google.common.base.Charsets; 4 | import io.netty.handler.codec.EncoderException; 5 | import net.minecraft.item.Item; 6 | import net.minecraft.item.ItemStack; 7 | import net.minecraftforge.fluids.FluidRegistry; 8 | import net.minecraftforge.fluids.FluidStack; 9 | 10 | public class MCDataIO 11 | { 12 | /** 13 | * PacketBuffer.readVarIntFromBuffer 14 | */ 15 | public static int readVarInt(MCDataInput in) { 16 | int i = 0; 17 | int j = 0; 18 | byte b0; 19 | 20 | do { 21 | b0 = in.readByte(); 22 | i |= (b0 & 127) << j++ * 7; 23 | 24 | if (j > 5) 25 | throw new RuntimeException("VarInt too big"); 26 | } while ((b0 & 128) == 128); 27 | 28 | return i; 29 | } 30 | 31 | public static int readVarShort(MCDataInput in) { 32 | int low = in.readUShort(); 33 | int high = 0; 34 | if ((low & 0x8000) != 0) { 35 | low = low & 0x7FFF; 36 | high = in.readUByte(); 37 | } 38 | return ((high & 0xFF) << 15) | low; 39 | } 40 | 41 | public static String readString(MCDataInput in) { 42 | return new String(in.readArray(in.readVarInt()), Charsets.UTF_8); 43 | } 44 | 45 | public static ItemStack readItemStack(MCDataInput in) { 46 | ItemStack item = null; 47 | short itemID = in.readShort(); 48 | 49 | if (itemID >= 0) { 50 | int stackSize = in.readVarInt(); 51 | short damage = in.readShort(); 52 | item = new ItemStack(Item.getItemById(itemID), stackSize, damage); 53 | item.setTagCompound(in.readNBTTagCompound()); 54 | } 55 | 56 | return item; 57 | } 58 | 59 | public static FluidStack readFluidStack(MCDataInput in) { 60 | FluidStack fluid = null; 61 | short fluidID = in.readShort(); 62 | 63 | if (fluidID >= 0) 64 | fluid = new FluidStack(FluidRegistry.getFluid(fluidID), in.readVarInt(), in.readNBTTagCompound()); 65 | 66 | return fluid; 67 | } 68 | 69 | /** 70 | * PacketBuffer.writeVarIntToBuffer 71 | */ 72 | public static void writeVarInt(MCDataOutput out, int i) { 73 | while ((i & 0x80) != 0) { 74 | out.writeByte(i & 0x7F | 0x80); 75 | i >>>= 7; 76 | } 77 | 78 | out.writeByte(i); 79 | } 80 | 81 | /** 82 | * ByteBufUtils.readVarShort 83 | */ 84 | public static void writeVarShort(MCDataOutput out, int s) { 85 | int low = s & 0x7FFF; 86 | int high = (s & 0x7F8000) >> 15; 87 | if (high != 0) 88 | low |= 0x8000; 89 | out.writeShort(low); 90 | if (high != 0) 91 | out.writeByte(high); 92 | } 93 | 94 | /** 95 | * PacketBuffer.writeString 96 | */ 97 | public static void writeString(MCDataOutput out, String string) { 98 | byte[] abyte = string.getBytes(Charsets.UTF_8); 99 | if (abyte.length > 32767) 100 | throw new EncoderException("String too big (was " + string.length() + " bytes encoded, max " + 32767 + ")"); 101 | 102 | out.writeVarInt(abyte.length); 103 | out.writeArray(abyte); 104 | } 105 | 106 | /** 107 | * Supports large stacks by writing stackSize as a varInt 108 | */ 109 | public static void writeItemStack(MCDataOutput out, ItemStack stack) { 110 | if (stack == null) { 111 | out.writeShort(-1); 112 | } else { 113 | out.writeShort(Item.getIdFromItem(stack.getItem())); 114 | out.writeVarInt(stack.stackSize); 115 | out.writeShort(stack.getItemDamage()); 116 | out.writeNBTTagCompound(stack.getItem().getShareTag() ? stack.getTagCompound() : null); 117 | } 118 | } 119 | 120 | public static void writeFluidStack(MCDataOutput out, FluidStack fluid) { 121 | if (fluid == null) { 122 | out.writeShort(-1); 123 | } else { 124 | out.writeShort(fluid.getFluid().getID()); 125 | out.writeVarInt(fluid.amount); 126 | out.writeNBTTagCompound(fluid.tag); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/codechicken/lib/data/MCDataInput.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.data; 2 | 3 | import codechicken.lib.vec.BlockCoord; 4 | import net.minecraft.item.ItemStack; 5 | import net.minecraft.nbt.NBTTagCompound; 6 | import net.minecraftforge.fluids.FluidStack; 7 | 8 | public interface MCDataInput 9 | { 10 | public long readLong(); 11 | public int readInt(); 12 | public short readShort(); 13 | public int readUShort(); 14 | public byte readByte(); 15 | public short readUByte(); 16 | public double readDouble(); 17 | public float readFloat(); 18 | public boolean readBoolean(); 19 | public char readChar(); 20 | public int readVarShort(); 21 | public int readVarInt(); 22 | public long readVarLong(); 23 | public byte[] readArray(int length); 24 | public String readString(); 25 | public BlockCoord readCoord(); 26 | public NBTTagCompound readNBTTagCompound(); 27 | public ItemStack readItemStack(); 28 | public FluidStack readFluidStack(); 29 | } 30 | -------------------------------------------------------------------------------- /src/codechicken/lib/data/MCDataInputStream.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.data; 2 | 3 | import java.io.InputStream; 4 | 5 | public class MCDataInputStream extends InputStream 6 | { 7 | private MCDataInput in; 8 | 9 | public MCDataInputStream(MCDataInput in) 10 | { 11 | this.in = in; 12 | } 13 | 14 | @Override 15 | public int read() 16 | { 17 | return in.readByte()&0xFF; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/codechicken/lib/data/MCDataOutput.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.data; 2 | 3 | import codechicken.lib.vec.BlockCoord; 4 | import net.minecraft.item.ItemStack; 5 | import net.minecraft.nbt.NBTTagCompound; 6 | import net.minecraftforge.fluids.FluidStack; 7 | 8 | public interface MCDataOutput 9 | { 10 | public MCDataOutput writeLong(long l); 11 | public MCDataOutput writeInt(int i); 12 | public MCDataOutput writeShort(int s); 13 | public MCDataOutput writeByte(int b); 14 | public MCDataOutput writeDouble(double d); 15 | public MCDataOutput writeFloat(float f); 16 | public MCDataOutput writeBoolean(boolean b); 17 | public MCDataOutput writeChar(char c); 18 | public MCDataOutput writeVarInt(int i); 19 | public MCDataOutput writeVarShort(int s); 20 | public MCDataOutput writeArray(byte[] array); 21 | public MCDataOutput writeString(String s); 22 | public MCDataOutput writeCoord(int x, int y, int z); 23 | public MCDataOutput writeCoord(BlockCoord coord); 24 | public MCDataOutput writeNBTTagCompound(NBTTagCompound tag); 25 | 26 | /** 27 | * Supports large stacks by writing stackSize as a varInt 28 | */ 29 | public MCDataOutput writeItemStack(ItemStack stack); 30 | public MCDataOutput writeFluidStack(FluidStack liquid); 31 | } 32 | -------------------------------------------------------------------------------- /src/codechicken/lib/data/MCDataOutputStream.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.data; 2 | 3 | import java.io.OutputStream; 4 | 5 | public class MCDataOutputStream extends OutputStream 6 | { 7 | private MCDataOutput out; 8 | 9 | public MCDataOutputStream(MCDataOutput out) 10 | { 11 | this.out = out; 12 | } 13 | 14 | @Override 15 | public void write(int b) 16 | { 17 | out.writeByte(b); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/codechicken/lib/data/MCDataOutputWrapper.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.data; 2 | 3 | import codechicken.lib.vec.BlockCoord; 4 | import io.netty.handler.codec.EncoderException; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.nbt.CompressedStreamTools; 7 | import net.minecraft.nbt.NBTTagCompound; 8 | import net.minecraftforge.fluids.FluidStack; 9 | 10 | import java.io.DataOutput; 11 | import java.io.IOException; 12 | 13 | public class MCDataOutputWrapper implements MCDataOutput 14 | { 15 | public DataOutput dataout; 16 | 17 | public MCDataOutputWrapper(DataOutput out) { 18 | dataout = out; 19 | } 20 | 21 | public MCDataOutputWrapper writeBoolean(boolean b) { 22 | try { 23 | dataout.writeBoolean(b); 24 | } catch (IOException e) { 25 | throw new EncoderException(e); 26 | } 27 | return this; 28 | } 29 | 30 | public MCDataOutputWrapper writeByte(int b) { 31 | try { 32 | dataout.writeByte(b); 33 | } catch (IOException e) { 34 | throw new EncoderException(e); 35 | } 36 | return this; 37 | } 38 | 39 | public MCDataOutputWrapper writeShort(int s) { 40 | try { 41 | dataout.writeShort(s); 42 | } catch (IOException e) { 43 | throw new EncoderException(e); 44 | } 45 | return this; 46 | } 47 | 48 | public MCDataOutputWrapper writeInt(int i) { 49 | try { 50 | dataout.writeInt(i); 51 | } catch (IOException e) { 52 | throw new EncoderException(e); 53 | } 54 | return this; 55 | } 56 | 57 | public MCDataOutputWrapper writeFloat(float f) { 58 | try { 59 | dataout.writeFloat(f); 60 | } catch (IOException e) { 61 | throw new EncoderException(e); 62 | } 63 | return this; 64 | } 65 | 66 | public MCDataOutputWrapper writeDouble(double d) { 67 | try { 68 | dataout.writeDouble(d); 69 | } catch (IOException e) { 70 | throw new EncoderException(e); 71 | } 72 | return this; 73 | } 74 | 75 | public MCDataOutputWrapper writeLong(long l) { 76 | try { 77 | dataout.writeLong(l); 78 | } catch (IOException e) { 79 | throw new EncoderException(e); 80 | } 81 | return this; 82 | } 83 | 84 | @Override 85 | public MCDataOutputWrapper writeChar(char c) { 86 | try { 87 | dataout.writeChar(c); 88 | } catch (IOException e) { 89 | throw new EncoderException(e); 90 | } 91 | return this; 92 | } 93 | 94 | @Override 95 | public MCDataOutput writeVarInt(int i) { 96 | MCDataIO.writeVarInt(this, i); 97 | return this; 98 | } 99 | 100 | @Override 101 | public MCDataOutput writeVarShort(int s) { 102 | MCDataIO.writeVarShort(this, s); 103 | return this; 104 | } 105 | 106 | public MCDataOutputWrapper writeArray(byte[] barray) { 107 | try { 108 | dataout.write(barray); 109 | } catch (IOException e) { 110 | throw new EncoderException(e); 111 | } 112 | return this; 113 | } 114 | 115 | public MCDataOutputWrapper writeCoord(int x, int y, int z) { 116 | writeInt(x); 117 | writeInt(y); 118 | writeInt(z); 119 | return this; 120 | } 121 | 122 | public MCDataOutputWrapper writeCoord(BlockCoord coord) { 123 | writeInt(coord.x); 124 | writeInt(coord.y); 125 | writeInt(coord.z); 126 | return this; 127 | } 128 | 129 | public MCDataOutputWrapper writeString(String s) { 130 | MCDataIO.writeString(this, s); 131 | return this; 132 | } 133 | 134 | public MCDataOutputWrapper writeItemStack(ItemStack stack) { 135 | MCDataIO.writeItemStack(this, stack); 136 | return this; 137 | } 138 | 139 | public MCDataOutputWrapper writeNBTTagCompound(NBTTagCompound nbt) { 140 | if (nbt == null) 141 | this.writeByte(0); 142 | else try { 143 | CompressedStreamTools.write(nbt, dataout); 144 | } catch (IOException ioexception) { 145 | throw new EncoderException(ioexception); 146 | } 147 | return this; 148 | } 149 | 150 | public MCDataOutputWrapper writeFluidStack(FluidStack fluid) { 151 | MCDataIO.writeFluidStack(this, fluid); 152 | return this; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/codechicken/lib/inventory/InventoryCopy.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.inventory; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.inventory.IInventory; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.util.ChatComponentText; 7 | import net.minecraft.util.IChatComponent; 8 | 9 | /** 10 | * Creates a copy of an IInventory for extended simulation 11 | */ 12 | public class InventoryCopy implements IInventory 13 | { 14 | public boolean[] accessible; 15 | public ItemStack[] items; 16 | public IInventory inv; 17 | 18 | public InventoryCopy(IInventory inv) { 19 | items = new ItemStack[inv.getSizeInventory()]; 20 | accessible = new boolean[inv.getSizeInventory()]; 21 | this.inv = inv; 22 | update(); 23 | } 24 | 25 | public void update() { 26 | for (int i = 0; i < items.length; i++) { 27 | ItemStack stack = inv.getStackInSlot(i); 28 | if (stack != null) 29 | items[i] = stack.copy(); 30 | } 31 | } 32 | 33 | public InventoryCopy open(InventoryRange access) { 34 | int lslot = access.lastSlot(); 35 | if (lslot > accessible.length) { 36 | boolean[] l_accessible = new boolean[lslot]; 37 | ItemStack[] l_items = new ItemStack[lslot]; 38 | System.arraycopy(accessible, 0, l_accessible, 0, accessible.length); 39 | System.arraycopy(items, 0, l_items, 0, items.length); 40 | accessible = l_accessible; 41 | items = l_items; 42 | } 43 | 44 | for (int slot : access.slots) 45 | accessible[slot] = true; 46 | return this; 47 | } 48 | 49 | @Override 50 | public int getSizeInventory() { 51 | return items.length; 52 | } 53 | 54 | @Override 55 | public ItemStack getStackInSlot(int slot) { 56 | return items[slot]; 57 | } 58 | 59 | public ItemStack decrStackSize(int slot, int amount) { 60 | return InventoryUtils.decrStackSize(this, slot, amount); 61 | } 62 | 63 | @Override 64 | public ItemStack removeStackFromSlot(int slot) { 65 | return InventoryUtils.getStackInSlotOnClosing(this, slot); 66 | } 67 | 68 | @Override 69 | public void setInventorySlotContents(int slot, ItemStack stack) { 70 | items[slot] = stack; 71 | markDirty(); 72 | } 73 | 74 | @Override 75 | public boolean isUseableByPlayer(EntityPlayer player) { 76 | return true; 77 | } 78 | 79 | @Override 80 | public int getInventoryStackLimit() { 81 | return 64; 82 | } 83 | 84 | @Override 85 | public void markDirty() {} 86 | 87 | @Override 88 | public boolean isItemValidForSlot(int i, ItemStack itemstack) { 89 | return inv.isItemValidForSlot(i, itemstack); 90 | } 91 | 92 | @Override 93 | public void openInventory(EntityPlayer player) {} 94 | 95 | @Override 96 | public void closeInventory(EntityPlayer player) {} 97 | 98 | @Override 99 | public int getField(int id) { 100 | return 0; 101 | } 102 | 103 | @Override 104 | public void setField(int id, int value) {} 105 | 106 | @Override 107 | public int getFieldCount() { 108 | return 0; 109 | } 110 | 111 | @Override 112 | public void clear() {} 113 | 114 | @Override 115 | public String getName() { 116 | return "copy"; 117 | } 118 | 119 | @Override 120 | public boolean hasCustomName() { 121 | return true; 122 | } 123 | 124 | @Override 125 | public IChatComponent getDisplayName() { 126 | return new ChatComponentText(getName()); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/codechicken/lib/inventory/InventoryNBT.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.inventory; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.inventory.IInventory; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.nbt.NBTTagCompound; 7 | import net.minecraft.util.ChatComponentText; 8 | import net.minecraft.util.IChatComponent; 9 | 10 | /** 11 | * IInventory implementation which saves and loads from an NBT tag 12 | */ 13 | public class InventoryNBT implements IInventory 14 | { 15 | protected ItemStack[] items; 16 | protected NBTTagCompound tag; 17 | 18 | public InventoryNBT(int size, NBTTagCompound tag) { 19 | this.tag = tag; 20 | items = new ItemStack[size]; 21 | readNBT(); 22 | } 23 | 24 | private void writeNBT() { 25 | tag.setTag("items", InventoryUtils.writeItemStacksToTag(items, getInventoryStackLimit())); 26 | } 27 | 28 | private void readNBT() { 29 | if (tag.hasKey("items")) 30 | InventoryUtils.readItemStacksFromTag(items, tag.getTagList("items", 10)); 31 | } 32 | 33 | @Override 34 | public int getSizeInventory() { 35 | return items.length; 36 | } 37 | 38 | @Override 39 | public ItemStack getStackInSlot(int slot) { 40 | return items[slot]; 41 | } 42 | 43 | @Override 44 | public ItemStack decrStackSize(int slot, int amount) { 45 | return InventoryUtils.decrStackSize(this, slot, amount); 46 | } 47 | 48 | @Override 49 | public ItemStack removeStackFromSlot(int slot) { 50 | return InventoryUtils.getStackInSlotOnClosing(this, slot); 51 | } 52 | 53 | @Override 54 | public void setInventorySlotContents(int slot, ItemStack stack) { 55 | items[slot] = stack; 56 | markDirty(); 57 | } 58 | 59 | @Override 60 | public int getInventoryStackLimit() { 61 | return 64; 62 | } 63 | 64 | @Override 65 | public void markDirty() { 66 | writeNBT(); 67 | } 68 | 69 | @Override 70 | public void clear() { 71 | for(int i = 0; i < items.length; i++) 72 | items[i] = null; 73 | markDirty(); 74 | } 75 | 76 | @Override 77 | public int getField(int id) { 78 | return 0; 79 | } 80 | 81 | @Override 82 | public void setField(int id, int value) {} 83 | 84 | @Override 85 | public int getFieldCount() { 86 | return 0; 87 | } 88 | 89 | @Override 90 | public boolean isUseableByPlayer(EntityPlayer var1) { 91 | return true; 92 | } 93 | 94 | @Override 95 | public void openInventory(EntityPlayer player) {} 96 | 97 | @Override 98 | public void closeInventory(EntityPlayer player) {} 99 | 100 | @Override 101 | public boolean isItemValidForSlot(int i, ItemStack itemstack) { 102 | return true; 103 | } 104 | 105 | @Override 106 | public String getName() { 107 | return "NBT"; 108 | } 109 | 110 | @Override 111 | public boolean hasCustomName() { 112 | return true; 113 | } 114 | 115 | @Override 116 | public IChatComponent getDisplayName() { 117 | return new ChatComponentText(getName()); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/codechicken/lib/inventory/InventoryRange.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.inventory; 2 | 3 | import net.minecraft.inventory.IInventory; 4 | import net.minecraft.inventory.ISidedInventory; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.util.EnumFacing; 7 | 8 | /** 9 | * Inventory wrapper for unified ISided/IInventory access 10 | */ 11 | public class InventoryRange 12 | { 13 | public IInventory inv; 14 | public EnumFacing face; 15 | public ISidedInventory sidedInv; 16 | public int[] slots; 17 | 18 | public InventoryRange(IInventory inv, int side) 19 | { 20 | this.inv = inv; 21 | this.face = EnumFacing.values()[side]; 22 | if(inv instanceof ISidedInventory) 23 | { 24 | sidedInv = (ISidedInventory)inv; 25 | slots = sidedInv.getSlotsForFace(face); 26 | } 27 | else 28 | { 29 | slots = new int[inv.getSizeInventory()]; 30 | for(int i = 0; i < slots.length; i++) 31 | slots[i] = i; 32 | } 33 | } 34 | 35 | public InventoryRange(IInventory inv) 36 | { 37 | this(inv, 0); 38 | } 39 | 40 | public InventoryRange(IInventory inv, int fslot, int lslot) 41 | { 42 | this.inv = inv; 43 | slots = new int[lslot-fslot]; 44 | for(int i = 0; i < slots.length; i++) 45 | slots[i] = fslot+i; 46 | } 47 | 48 | public InventoryRange(IInventory inv, InventoryRange access) 49 | { 50 | this.inv = inv; 51 | this.slots = access.slots; 52 | this.face = access.face; 53 | if(inv instanceof ISidedInventory) 54 | sidedInv = (ISidedInventory) inv; 55 | } 56 | 57 | public boolean canInsertItem(int slot, ItemStack item) 58 | { 59 | return sidedInv == null ? inv.isItemValidForSlot(slot, item) : sidedInv.canInsertItem(slot, item, face); 60 | } 61 | 62 | public boolean canExtractItem(int slot, ItemStack item) 63 | { 64 | return sidedInv == null ? inv.isItemValidForSlot(slot, item) : sidedInv.canExtractItem(slot, item, face); 65 | } 66 | 67 | public int lastSlot() 68 | { 69 | int last = 0; 70 | for(int slot : slots) 71 | if(slot > last) 72 | last = slot; 73 | return last; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/codechicken/lib/inventory/InventorySimple.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.inventory; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.inventory.IInventory; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.util.ChatComponentText; 7 | import net.minecraft.util.IChatComponent; 8 | 9 | /** 10 | * Simple IInventory implementation with an array of items, name and maximum stack size 11 | */ 12 | public class InventorySimple implements IInventory 13 | { 14 | public ItemStack[] items; 15 | public int limit; 16 | public String name; 17 | 18 | public InventorySimple(ItemStack[] items, int limit, String name) { 19 | this.items = items; 20 | this.limit = limit; 21 | this.name = name; 22 | } 23 | 24 | public InventorySimple(ItemStack[] items, String name) { 25 | this(items, 64, name); 26 | } 27 | 28 | public InventorySimple(ItemStack[] items, int limit) { 29 | this(items, limit, "inv"); 30 | } 31 | 32 | public InventorySimple(ItemStack[] items) { 33 | this(items, 64, "inv"); 34 | } 35 | 36 | public InventorySimple(int size, int limit, String name) { 37 | this(new ItemStack[size], limit, name); 38 | } 39 | 40 | public InventorySimple(int size, int limit) { 41 | this(size, limit, "inv"); 42 | } 43 | 44 | public InventorySimple(int size, String name) { 45 | this(size, 64, name); 46 | } 47 | 48 | public InventorySimple(int size) { 49 | this(size, 64, "inv"); 50 | } 51 | 52 | @Override 53 | public int getSizeInventory() { 54 | return items.length; 55 | } 56 | 57 | @Override 58 | public ItemStack getStackInSlot(int slot) { 59 | return items[slot]; 60 | } 61 | 62 | @Override 63 | public ItemStack decrStackSize(int slot, int amount) { 64 | return InventoryUtils.decrStackSize(this, slot, amount); 65 | } 66 | 67 | @Override 68 | public ItemStack removeStackFromSlot(int slot) { 69 | return InventoryUtils.getStackInSlotOnClosing(this, slot); 70 | } 71 | 72 | @Override 73 | public void setInventorySlotContents(int slot, ItemStack stack) { 74 | items[slot] = stack; 75 | markDirty(); 76 | } 77 | 78 | @Override 79 | public int getInventoryStackLimit() { 80 | return limit; 81 | } 82 | 83 | @Override 84 | public boolean isUseableByPlayer(EntityPlayer var1) { 85 | return true; 86 | } 87 | 88 | @Override 89 | public boolean isItemValidForSlot(int i, ItemStack itemstack) { 90 | return true; 91 | } 92 | 93 | @Override 94 | public void markDirty() {} 95 | 96 | @Override 97 | public void openInventory(EntityPlayer player) {} 98 | 99 | @Override 100 | public void closeInventory(EntityPlayer player) {} 101 | 102 | @Override 103 | public int getField(int id) { 104 | return 0; 105 | } 106 | 107 | @Override 108 | public void setField(int id, int value) {} 109 | 110 | @Override 111 | public int getFieldCount() { 112 | return 0; 113 | } 114 | 115 | @Override 116 | public void clear() {} 117 | 118 | @Override 119 | public String getName() { 120 | return "name"; 121 | } 122 | 123 | @Override 124 | public boolean hasCustomName() { 125 | return true; 126 | } 127 | 128 | @Override 129 | public IChatComponent getDisplayName() { 130 | return new ChatComponentText(getName()); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/codechicken/lib/inventory/ItemKey.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.inventory; 2 | 3 | import com.google.common.base.Objects; 4 | import net.minecraft.item.Item; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.nbt.NBTTagCompound; 7 | import net.minecraftforge.oredict.OreDictionary; 8 | 9 | import static codechicken.lib.inventory.InventoryUtils.actualDamage; 10 | 11 | /** 12 | * Comparable ItemStack with a hashCode implementation. 13 | */ 14 | public class ItemKey implements Comparable 15 | { 16 | public ItemStack stack; 17 | private int hashcode = 0; 18 | 19 | public ItemKey(ItemStack k) { 20 | stack = k; 21 | } 22 | 23 | public ItemKey(Item item, int damage) { 24 | this(new ItemStack(item, 1, damage)); 25 | } 26 | 27 | public ItemKey(Item item, NBTTagCompound tag) { 28 | this(item, OreDictionary.WILDCARD_VALUE, tag); 29 | } 30 | 31 | public ItemKey(Item item, int damage, NBTTagCompound tag) { 32 | this(item, damage); 33 | stack.setTagCompound(tag); 34 | } 35 | 36 | @Override 37 | public boolean equals(Object obj) { 38 | if (!(obj instanceof ItemKey)) 39 | return false; 40 | 41 | ItemKey k = (ItemKey) obj; 42 | return stack.getItem() == k.stack.getItem() && 43 | actualDamage(stack) == actualDamage(k.stack) && 44 | Objects.equal(stack.getTagCompound(), k.stack.getTagCompound()); 45 | } 46 | 47 | @Override 48 | public int hashCode() { 49 | return hashcode != 0 ? hashcode : (hashcode = Objects.hashCode(stack.getItem(), actualDamage(stack), stack.getTagCompound())); 50 | } 51 | 52 | public int compareInt(int a, int b) { 53 | return a == b ? 0 : a < b ? -1 : 1; 54 | } 55 | 56 | @Override 57 | public int compareTo(ItemKey o) { 58 | if (stack.getItem() != o.stack.getItem()) 59 | return compareInt(Item.getIdFromItem(stack.getItem()), Item.getIdFromItem(o.stack.getItem())); 60 | if (actualDamage(stack) != actualDamage(o.stack)) 61 | return compareInt(actualDamage(stack), actualDamage(o.stack)); 62 | return 0; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/codechicken/lib/lighting/LC.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.lighting; 2 | 3 | import codechicken.lib.render.CCModel; 4 | import codechicken.lib.util.Copyable; 5 | import codechicken.lib.vec.Rotation; 6 | import codechicken.lib.vec.Vector3; 7 | 8 | public class LC implements Copyable 9 | { 10 | public int side; 11 | public float fa; 12 | public float fb; 13 | public float fc; 14 | public float fd; 15 | 16 | public LC() { 17 | this(0, 0, 0, 0, 0); 18 | } 19 | 20 | public LC(int s, float a, float b, float c, float d) { 21 | side = s; 22 | fa = a; 23 | fb = b; 24 | fc = c; 25 | fd = d; 26 | } 27 | 28 | public LC set(int s, float a, float b, float c, float d) { 29 | side = s; 30 | fa = a; 31 | fb = b; 32 | fc = c; 33 | fd = d; 34 | return this; 35 | } 36 | 37 | public LC set(LC lc) { 38 | return set(lc.side, lc.fa, lc.fb, lc.fc, lc.fd); 39 | } 40 | 41 | public LC compute(Vector3 vec, Vector3 normal) { 42 | int side = CCModel.findSide(normal); 43 | if (side < 0) 44 | return set(12, 1, 0, 0, 0); 45 | return compute(vec, side); 46 | } 47 | 48 | public LC compute(Vector3 vec, int side) { 49 | boolean offset = false; 50 | switch (side) { 51 | case 0: 52 | offset = vec.y <= 0; 53 | break; 54 | case 1: 55 | offset = vec.y >= 1; 56 | break; 57 | case 2: 58 | offset = vec.z <= 0; 59 | break; 60 | case 3: 61 | offset = vec.z >= 1; 62 | break; 63 | case 4: 64 | offset = vec.x <= 0; 65 | break; 66 | case 5: 67 | offset = vec.x >= 1; 68 | break; 69 | } 70 | if (!offset) 71 | side += 6; 72 | return computeO(vec, side); 73 | } 74 | 75 | public LC computeO(Vector3 vec, int side) { 76 | Vector3 v1 = Rotation.axes[((side & 0xE) + 3) % 6]; 77 | Vector3 v2 = Rotation.axes[((side & 0xE) + 5) % 6]; 78 | float d1 = (float) vec.scalarProject(v1); 79 | float d2 = 1 - d1; 80 | float d3 = (float) vec.scalarProject(v2); 81 | float d4 = 1 - d3; 82 | return set(side, d2 * d4, d2 * d3, d1 * d4, d1 * d3); 83 | } 84 | 85 | @Override 86 | public LC copy() { 87 | return new LC(side, fa, fb, fc, fd); 88 | } 89 | } -------------------------------------------------------------------------------- /src/codechicken/lib/lighting/LightMatrix.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.lighting; 2 | 3 | import codechicken.lib.colour.ColourRGBA; 4 | import codechicken.lib.render.CCRenderState; 5 | import codechicken.lib.vec.BlockCoord; 6 | import net.minecraft.block.Block; 7 | import net.minecraft.block.state.IBlockState; 8 | import net.minecraft.client.Minecraft; 9 | import net.minecraft.util.BlockPos; 10 | import net.minecraft.world.IBlockAccess; 11 | 12 | /** 13 | * Note that when using the class as a vertex transformer, the vertices are assumed to be within the BB (x, y, z) -> (x+1, y+1, z+1) 14 | */ 15 | public class LightMatrix implements CCRenderState.IVertexOperation 16 | { 17 | public static final int operationIndex = CCRenderState.registerOperation(); 18 | 19 | public int computed = 0; 20 | public float[][] ao = new float[13][4]; 21 | public int[][] brightness = new int[13][4]; 22 | 23 | public IBlockAccess access; 24 | public BlockCoord pos = new BlockCoord(); 25 | 26 | private int sampled = 0; 27 | private float[] aSamples = new float[27]; 28 | private int[] bSamples = new int[27]; 29 | 30 | /** 31 | * The 9 positions in the sample array for each side, sides >= 6 are centered on sample 13 (the block itself) 32 | */ 33 | public static final int[][] ssamplem = new int[][]{ 34 | { 0, 1, 2, 3, 4, 5, 6, 7, 8}, 35 | {18,19,20,21,22,23,24,25,26}, 36 | { 0, 9,18, 1,10,19, 2,11,20}, 37 | { 6,15,24, 7,16,25, 8,17,26}, 38 | { 0, 3, 6, 9,12,15,18,21,24}, 39 | { 2, 5, 8,11,14,17,20,23,26}, 40 | { 9,10,11,12,13,14,15,16,17}, 41 | { 9,10,11,12,13,14,15,16,17}, 42 | { 3,12,21, 4,13,22, 5,14,23}, 43 | { 3,12,21, 4,13,22, 5,14,23}, 44 | { 1, 4, 7,10,13,16,19,22,25}, 45 | { 1, 4, 7,10,13,16,19,22,25}, 46 | {13,13,13,13,13,13,13,13,13}}; 47 | public static final int[][] qsamplem = new int[][]{//the positions in the side sample array for each corner 48 | {0,1,3,4}, 49 | {5,1,2,4}, 50 | {6,7,3,4}, 51 | {5,7,8,4}}; 52 | public static final float[] sideao = new float[]{ 53 | 0.5F, 1F, 0.8F, 0.8F, 0.6F, 0.6F, 54 | 0.5F, 1F, 0.8F, 0.8F, 0.6F, 0.6F, 55 | 1F}; 56 | 57 | /*static 58 | { 59 | int[][] os = new int[][]{ 60 | {0,-1,0}, 61 | {0, 1,0}, 62 | {0,0,-1}, 63 | {0,0, 1}, 64 | {-1,0,0}, 65 | { 1,0,0}}; 66 | 67 | for(int s = 0; s < 12; s++) 68 | { 69 | int[] d0 = s < 6 ? new int[]{os[s][0]+1, os[s][1]+1, os[s][2]+1} : new int[]{1, 1, 1}; 70 | int[] d1 = os[((s&0xE)+3)%6]; 71 | int[] d2 = os[((s&0xE)+5)%6]; 72 | for(int a = -1; a <= 1; a++) 73 | for(int b = -1; b <= 1; b++) 74 | ssamplem[s][(a+1)*3+b+1] = (d0[1]+d1[1]*a+d2[1]*b)*9+(d0[2]+d1[2]*a+d2[2]*b)*3+(d0[0]+d1[0]*a+d2[0]*b); 75 | } 76 | System.out.println(Arrays.deepToString(ssamplem)); 77 | }*/ 78 | 79 | public void locate(IBlockAccess a, int x, int y, int z) { 80 | access = a; 81 | pos.set(x, y, z); 82 | computed = 0; 83 | sampled = 0; 84 | } 85 | 86 | public void sample(int i) { 87 | if ((sampled & 1 << i) == 0) { 88 | BlockPos bp = new BlockPos(pos.x + (i % 3) - 1, pos.y + (i / 9) - 1, pos.z + (i / 3 % 3) - 1); 89 | IBlockState b = access.getBlockState(bp); 90 | bSamples[i] = access.getCombinedLight(bp, b.getBlock().getLightValue(access, bp)); 91 | aSamples[i] = b.getBlock().getAmbientOcclusionLightValue(); 92 | sampled |= 1 << i; 93 | } 94 | } 95 | 96 | public int[] brightness(int side) { 97 | sideSample(side); 98 | return brightness[side]; 99 | } 100 | 101 | public float[] ao(int side) { 102 | sideSample(side); 103 | return ao[side]; 104 | } 105 | 106 | public void sideSample(int side) { 107 | if ((computed & 1 << side) == 0) { 108 | int[] ssample = ssamplem[side]; 109 | for (int q = 0; q < 4; q++) { 110 | int[] qsample = qsamplem[q]; 111 | if (Minecraft.isAmbientOcclusionEnabled()) 112 | interp(side, q, ssample[qsample[0]], ssample[qsample[1]], ssample[qsample[2]], ssample[qsample[3]]); 113 | else 114 | interp(side, q, ssample[4], ssample[4], ssample[4], ssample[4]); 115 | } 116 | computed |= 1 << side; 117 | } 118 | } 119 | 120 | private void interp(int s, int q, int a, int b, int c, int d) { 121 | sample(a); sample(b); sample(c); sample(d); 122 | ao[s][q] = interpAO(aSamples[a], aSamples[b], aSamples[c], aSamples[d])*sideao[s]; 123 | brightness[s][q] = interpBrightness(bSamples[a], bSamples[b], bSamples[c], bSamples[d]); 124 | } 125 | 126 | public static float interpAO(float a, float b, float c, float d) { 127 | return (a + b + c + d) / 4F; 128 | } 129 | 130 | public static int interpBrightness(int a, int b, int c, int d) { 131 | if (a == 0) 132 | a = d; 133 | if (b == 0) 134 | b = d; 135 | if (c == 0) 136 | c = d; 137 | return (a + b + c + d) >> 2 & 0xFF00FF; 138 | } 139 | 140 | @Override 141 | public boolean load() { 142 | if(!CCRenderState.computeLighting) 143 | return false; 144 | 145 | CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); 146 | CCRenderState.pipeline.addDependency(CCRenderState.lightCoordAttrib); 147 | return true; 148 | } 149 | 150 | @Override 151 | public void operate() { 152 | LC lc = CCRenderState.lc; 153 | float[] a = ao(lc.side); 154 | float f = (a[0] * lc.fa + a[1] * lc.fb + a[2] * lc.fc + a[3] * lc.fd); 155 | int[] b = brightness(lc.side); 156 | CCRenderState.setColour(ColourRGBA.multiplyC(CCRenderState.colour, f)); 157 | CCRenderState.setBrightness((int) (b[0] * lc.fa + b[1] * lc.fb + b[2] * lc.fc + b[3] * lc.fd) & 0xFF00FF); 158 | } 159 | 160 | @Override 161 | public int operationID() { 162 | return operationIndex; 163 | } 164 | } -------------------------------------------------------------------------------- /src/codechicken/lib/lighting/LightModel.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.lighting; 2 | 3 | import codechicken.lib.render.CCRenderState; 4 | import codechicken.lib.vec.Rotation; 5 | import codechicken.lib.vec.Vector3; 6 | 7 | public class LightModel implements CCRenderState.IVertexOperation 8 | { 9 | public static final int operationIndex = CCRenderState.registerOperation(); 10 | 11 | public static class Light 12 | { 13 | public Vector3 ambient = new Vector3(); 14 | public Vector3 diffuse = new Vector3(); 15 | public Vector3 position; 16 | 17 | public Light(Vector3 pos) { 18 | position = pos.copy().normalize(); 19 | } 20 | 21 | public Light setDiffuse(Vector3 vec) { 22 | diffuse.set(vec); 23 | return this; 24 | } 25 | 26 | public Light setAmbient(Vector3 vec) { 27 | ambient.set(vec); 28 | return this; 29 | } 30 | } 31 | 32 | public static LightModel standardLightModel; 33 | static { 34 | standardLightModel = new LightModel() 35 | .setAmbient(new Vector3(0.4, 0.4, 0.4)) 36 | .addLight(new Light(new Vector3(0.2, 1, -0.7)) 37 | .setDiffuse(new Vector3(0.6, 0.6, 0.6))) 38 | .addLight(new Light(new Vector3(-0.2, 1, 0.7)) 39 | .setDiffuse(new Vector3(0.6, 0.6, 0.6))); 40 | } 41 | 42 | private Vector3 ambient = new Vector3(); 43 | private Light[] lights = new Light[8]; 44 | private int lightCount; 45 | 46 | public LightModel addLight(Light light) { 47 | lights[lightCount++] = light; 48 | return this; 49 | } 50 | 51 | public LightModel setAmbient(Vector3 vec) { 52 | ambient.set(vec); 53 | return this; 54 | } 55 | 56 | /** 57 | * @param colour The pre-lighting vertex colour. RGBA format 58 | * @param normal The normal at the vertex 59 | * @return The lighting applied colour 60 | */ 61 | public int apply(int colour, Vector3 normal) { 62 | Vector3 n_colour = ambient.copy(); 63 | for (int l = 0; l < lightCount; l++) { 64 | Light light = lights[l]; 65 | double n_l = light.position.dotProduct(normal); 66 | double f = n_l > 0 ? 1 : 0; 67 | n_colour.x += light.ambient.x + f * light.diffuse.x * n_l; 68 | n_colour.y += light.ambient.y + f * light.diffuse.y * n_l; 69 | n_colour.z += light.ambient.z + f * light.diffuse.z * n_l; 70 | } 71 | 72 | if (n_colour.x > 1) 73 | n_colour.x = 1; 74 | if (n_colour.y > 1) 75 | n_colour.y = 1; 76 | if (n_colour.z > 1) 77 | n_colour.z = 1; 78 | 79 | n_colour.multiply((colour >>> 24) / 255D, (colour >> 16 & 0xFF) / 255D, (colour >> 8 & 0xFF) / 255D); 80 | return (int) (n_colour.x * 255) << 24 | (int) (n_colour.y * 255) << 16 | (int) (n_colour.z * 255) << 8 | colour & 0xFF; 81 | } 82 | 83 | @Override 84 | public boolean load() { 85 | if(!CCRenderState.computeLighting) 86 | return false; 87 | 88 | CCRenderState.pipeline.addDependency(CCRenderState.normalAttrib); 89 | CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); 90 | return true; 91 | } 92 | 93 | @Override 94 | public void operate() { 95 | CCRenderState.setColour(apply(CCRenderState.colour, CCRenderState.normal)); 96 | } 97 | 98 | @Override 99 | public int operationID() { 100 | return operationIndex; 101 | } 102 | 103 | public PlanarLightModel reducePlanar() { 104 | int[] colours = new int[6]; 105 | for (int i = 0; i < 6; i++) 106 | colours[i] = apply(-1, Rotation.axes[i]); 107 | return new PlanarLightModel(colours); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/codechicken/lib/lighting/PlanarLightMatrix.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.lighting; 2 | 3 | import codechicken.lib.render.CCRenderState; 4 | import codechicken.lib.vec.BlockCoord; 5 | import net.minecraft.block.Block; 6 | import net.minecraft.block.state.IBlockState; 7 | import net.minecraft.util.BlockPos; 8 | import net.minecraft.world.IBlockAccess; 9 | 10 | public class PlanarLightMatrix extends PlanarLightModel 11 | { 12 | public static final int operationIndex = CCRenderState.registerOperation(); 13 | public static PlanarLightMatrix instance = new PlanarLightMatrix(); 14 | 15 | public IBlockAccess access; 16 | public BlockCoord pos = new BlockCoord(); 17 | 18 | private int sampled = 0; 19 | public int[] brightness = new int[6]; 20 | 21 | public PlanarLightMatrix() { 22 | super(PlanarLightModel.standardLightModel.colours); 23 | } 24 | 25 | public PlanarLightMatrix locate(IBlockAccess a, int x, int y, int z) { 26 | access = a; 27 | pos.set(x, y, z); 28 | sampled = 0; 29 | return this; 30 | } 31 | 32 | public int brightness(int side) { 33 | if((sampled & 1 << side) == 0) { 34 | BlockPos bp = pos.pos(); 35 | IBlockState b = access.getBlockState(bp); 36 | brightness[side] = access.getCombinedLight(bp, b.getBlock().getLightValue(access, bp)); 37 | sampled |= 1 << side; 38 | } 39 | return brightness[side]; 40 | } 41 | 42 | @Override 43 | public boolean load() { 44 | CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); 45 | return true; 46 | } 47 | 48 | @Override 49 | public void operate() { 50 | super.operate(); 51 | CCRenderState.setBrightness(brightness(CCRenderState.side)); 52 | } 53 | 54 | @Override 55 | public int operationID() { 56 | return operationIndex; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/codechicken/lib/lighting/PlanarLightModel.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.lighting; 2 | 3 | import codechicken.lib.colour.ColourRGBA; 4 | import codechicken.lib.render.CCRenderState; 5 | 6 | /** 7 | * Faster precomputed version of LightModel that only works for axis planar sides 8 | */ 9 | public class PlanarLightModel implements CCRenderState.IVertexOperation 10 | { 11 | public static PlanarLightModel standardLightModel = LightModel.standardLightModel.reducePlanar(); 12 | 13 | public int[] colours; 14 | 15 | public PlanarLightModel(int[] colours) { 16 | this.colours = colours; 17 | } 18 | 19 | @Override 20 | public boolean load() { 21 | if(!CCRenderState.computeLighting) 22 | return false; 23 | 24 | CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); 25 | CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); 26 | return true; 27 | } 28 | 29 | @Override 30 | public void operate() { 31 | CCRenderState.setColour(ColourRGBA.multiply(CCRenderState.colour, colours[CCRenderState.side])); 32 | } 33 | 34 | @Override 35 | public int operationID() { 36 | return LightModel.operationIndex; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/codechicken/lib/lighting/SimpleBrightnessModel.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.lighting; 2 | 3 | import codechicken.lib.render.CCRenderState; 4 | import codechicken.lib.vec.BlockCoord; 5 | import net.minecraft.block.Block; 6 | import net.minecraft.block.state.IBlockState; 7 | import net.minecraft.util.BlockPos; 8 | import net.minecraft.world.IBlockAccess; 9 | 10 | /** 11 | * Faster precomputed version of LightModel that only works for axis planar sides 12 | */ 13 | public class SimpleBrightnessModel implements CCRenderState.IVertexOperation 14 | { 15 | public static final int operationIndex = CCRenderState.registerOperation(); 16 | public static SimpleBrightnessModel instance = new SimpleBrightnessModel(); 17 | 18 | public IBlockAccess access; 19 | public BlockCoord pos = new BlockCoord(); 20 | 21 | private int sampled = 0; 22 | private int[] samples = new int[6]; 23 | private BlockCoord c = new BlockCoord(); 24 | 25 | public void locate(IBlockAccess a, int x, int y, int z) { 26 | access = a; 27 | pos.set(x, y, z); 28 | sampled = 0; 29 | } 30 | 31 | public int sample(int side) { 32 | if ((sampled & 1 << side) == 0) { 33 | BlockPos bp = c.set(pos).offset(side).pos(); 34 | IBlockState b = access.getBlockState(bp); 35 | samples[side] = access.getCombinedLight(bp, b.getBlock().getLightValue(access, bp)); 36 | sampled |= 1 << side; 37 | } 38 | return samples[side]; 39 | } 40 | 41 | @Override 42 | public boolean load() { 43 | CCRenderState.pipeline.addDependency(CCRenderState.sideAttrib); 44 | return true; 45 | } 46 | 47 | @Override 48 | public void operate() { 49 | CCRenderState.setBrightness(sample(CCRenderState.side)); 50 | } 51 | 52 | @Override 53 | public int operationID() { 54 | return operationIndex; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/codechicken/lib/math/MathHelper.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.math; 2 | 3 | public class MathHelper 4 | { 5 | public static final double phi = 1.618033988749894; 6 | public static final double pi = Math.PI; 7 | public static final double todeg = 57.29577951308232; 8 | public static final double torad = 0.017453292519943; 9 | public static final double sqrt2 = 1.414213562373095; 10 | 11 | public static double[] SIN_TABLE = new double[65536]; 12 | static 13 | { 14 | for (int i = 0; i < 65536; ++i) 15 | SIN_TABLE[i] = Math.sin(i / 65536D * 2 * Math.PI); 16 | 17 | SIN_TABLE[0] = 0; 18 | SIN_TABLE[16384] = 1; 19 | SIN_TABLE[32768] = 0; 20 | SIN_TABLE[49152] = 1; 21 | } 22 | 23 | public static double sin(double d) 24 | { 25 | return SIN_TABLE[(int)((float)d * 10430.378F) & 65535]; 26 | } 27 | 28 | public static double cos(double d) 29 | { 30 | return SIN_TABLE[(int)((float)d * 10430.378F + 16384.0F) & 65535]; 31 | } 32 | 33 | /** 34 | * @param a The value 35 | * @param b The value to approach 36 | * @param max The maximum step 37 | * @return the closed value to b no less than max from a 38 | */ 39 | public static float approachLinear(float a, float b, float max) 40 | { 41 | return (a > b) ? 42 | (a - b < max ? b : a-max) : 43 | (b - a < max ? b : a+max); 44 | } 45 | 46 | /** 47 | * @param a The value 48 | * @param b The value to approach 49 | * @param max The maximum step 50 | * @return the closed value to b no less than max from a 51 | */ 52 | public static double approachLinear(double a, double b, double max) 53 | { 54 | return (a > b) ? 55 | (a - b < max ? b : a-max) : 56 | (b - a < max ? b : a+max); 57 | } 58 | 59 | /** 60 | * @param a The first value 61 | * @param b The second value 62 | * @param d The interpolation factor, between 0 and 1 63 | * @return a+(b-a)*d 64 | */ 65 | public static float interpolate(float a, float b, float d) 66 | { 67 | return a+(b-a)*d; 68 | } 69 | 70 | /** 71 | * @param a The first value 72 | * @param b The second value 73 | * @param d The interpolation factor, between 0 and 1 74 | * @return a+(b-a)*d 75 | */ 76 | public static double interpolate(double a, double b, double d) 77 | { 78 | return a+(b-a)*d; 79 | } 80 | 81 | /** 82 | * @param a The value 83 | * @param b The value to approach 84 | * @param ratio The ratio to reduce the difference by 85 | * @return a+(b-a)*ratio 86 | */ 87 | public static double approachExp(double a, double b, double ratio) 88 | { 89 | return a+(b-a)*ratio; 90 | } 91 | 92 | /** 93 | * @param a The value 94 | * @param b The value to approach 95 | * @param ratio The ratio to reduce the difference by 96 | * @param cap The maximum amount to advance by 97 | * @return a+(b-a)*ratio 98 | */ 99 | public static double approachExp(double a, double b, double ratio, double cap) 100 | { 101 | double d = (b-a)*ratio; 102 | if(Math.abs(d) > cap) 103 | d = Math.signum(d)*cap; 104 | return a+d; 105 | } 106 | 107 | /** 108 | * @param a The value 109 | * @param b The value to approach 110 | * @param ratio The ratio to reduce the difference by 111 | * @param c The value to retreat from 112 | * @param kick The difference when a == c 113 | * @return 114 | */ 115 | public static double retreatExp(double a, double b, double c, double ratio, double kick) 116 | { 117 | double d = (Math.abs(c-a)+kick)*ratio; 118 | if(d > Math.abs(b-a)) 119 | return b; 120 | return a+Math.signum(b-a)*d; 121 | } 122 | 123 | /** 124 | * 125 | * @param value The value 126 | * @param min The min value 127 | * @param max The max value 128 | * @return The clipped value between min and max 129 | */ 130 | public static double clip(double value, double min, double max) 131 | { 132 | if(value > max) 133 | value = max; 134 | if(value < min) 135 | value = min; 136 | return value; 137 | } 138 | 139 | /** 140 | * @return a <= x <= b 141 | */ 142 | public static boolean between(double a, double x, double b) 143 | { 144 | return a <= x && x <= b; 145 | } 146 | 147 | public static int approachExpI(int a, int b, double ratio) 148 | { 149 | int r = (int)Math.round(approachExp(a, b, ratio)); 150 | return r == a ? b : r; 151 | } 152 | 153 | public static int retreatExpI(int a, int b, int c, double ratio, int kick) 154 | { 155 | int r = (int)Math.round(retreatExp(a, b, c, ratio, kick)); 156 | return r == a ? b : r; 157 | } 158 | 159 | public static int floor_double(double d) 160 | { 161 | return net.minecraft.util.MathHelper.floor_double(d); 162 | } 163 | 164 | public static int roundAway(double d) 165 | { 166 | return (int) (d < 0 ? Math.floor(d) : Math.ceil(d)); 167 | } 168 | 169 | public static int compare(int a, int b) 170 | { 171 | return a == b ? 0 : a < b ? -1 : 1; 172 | } 173 | 174 | public static int compare(double a, double b) 175 | { 176 | return a == b ? 0 : a < b ? -1 : 1; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/codechicken/lib/packet/ICustomPacketTile.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.packet; 2 | 3 | public interface ICustomPacketTile 4 | { 5 | public void handleDescriptionPacket(PacketCustom packet); 6 | } 7 | -------------------------------------------------------------------------------- /src/codechicken/lib/raytracer/ExtendedMOP.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.raytracer; 2 | 3 | import codechicken.lib.vec.BlockCoord; 4 | import codechicken.lib.vec.Vector3; 5 | import net.minecraft.entity.Entity; 6 | import net.minecraft.util.BlockPos; 7 | import net.minecraft.util.EnumFacing; 8 | import net.minecraft.util.MovingObjectPosition; 9 | 10 | public class ExtendedMOP extends MovingObjectPosition implements Comparable 11 | { 12 | /** 13 | * The square distance from the start of the raytrace. 14 | */ 15 | public double dist; 16 | 17 | public ExtendedMOP(Entity entity, Vector3 hit, Object data, double dist) { 18 | super(entity, hit.vec3()); 19 | setData(data); 20 | this.dist = dist; 21 | } 22 | 23 | public ExtendedMOP(Vector3 hit, int side, BlockCoord pos, Object data, double dist) { 24 | super(hit.vec3(), EnumFacing.values()[side], pos.pos()); 25 | setData(data); 26 | this.dist = dist; 27 | } 28 | 29 | public void setData(Object data) { 30 | if (data instanceof Integer) 31 | subHit = ((Integer) data).intValue(); 32 | hitInfo = data; 33 | } 34 | 35 | @Override 36 | public int compareTo(ExtendedMOP o) { 37 | return dist == o.dist ? 0 : dist < o.dist ? -1 : 1; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/codechicken/lib/raytracer/IndexedCuboid6.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.raytracer; 2 | 3 | import codechicken.lib.vec.Cuboid6; 4 | 5 | public class IndexedCuboid6 extends Cuboid6 6 | { 7 | public Object data; 8 | 9 | public IndexedCuboid6(Object data, Cuboid6 cuboid) 10 | { 11 | super(cuboid); 12 | this.data = data; 13 | } 14 | } -------------------------------------------------------------------------------- /src/codechicken/lib/render/CCModelLibrary.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import codechicken.lib.vec.*; 4 | 5 | import static codechicken.lib.math.MathHelper.phi; 6 | 7 | public class CCModelLibrary 8 | { 9 | public static CCModel icosahedron4; 10 | public static CCModel icosahedron7; 11 | 12 | private static int i; 13 | 14 | static 15 | { 16 | generateIcosahedron(); 17 | } 18 | 19 | private static void generateIcosahedron() 20 | { 21 | Vector3[] verts = new Vector3[12]; 22 | 23 | verts[0] = new Vector3(-1, phi, 0); 24 | verts[1] = new Vector3( 1, phi, 0); 25 | verts[2] = new Vector3( 1,-phi, 0); 26 | verts[3] = new Vector3(-1,-phi, 0); 27 | 28 | verts[4] = new Vector3(0,-1, phi); 29 | verts[5] = new Vector3(0, 1, phi); 30 | verts[6] = new Vector3(0, 1,-phi); 31 | verts[7] = new Vector3(0,-1,-phi); 32 | 33 | verts[8] = new Vector3( phi, 0,-1); 34 | verts[9] = new Vector3( phi, 0, 1); 35 | verts[10] = new Vector3(-phi, 0, 1); 36 | verts[11] = new Vector3(-phi, 0,-1); 37 | 38 | Quat quat = Quat.aroundAxis(0, 0, 1, Math.atan(1/phi)); 39 | for(Vector3 vec : verts) 40 | quat.rotate(vec); 41 | 42 | icosahedron4 = CCModel.newModel(4, 60); 43 | icosahedron7 = CCModel.newModel(7, 80); 44 | 45 | i = 0; 46 | //top 47 | addIcosahedronTriangle(verts[1], 0.5, 0, verts[0], 0, 0.25, verts[5], 1, 0.25); 48 | addIcosahedronTriangle(verts[1], 0.5, 0, verts[5], 0, 0.25, verts[9], 1, 0.25); 49 | addIcosahedronTriangle(verts[1], 0.5, 0, verts[9], 0, 0.25, verts[8], 1, 0.25); 50 | addIcosahedronTriangle(verts[1], 0.5, 0, verts[8], 0, 0.25, verts[6], 1, 0.25); 51 | addIcosahedronTriangle(verts[1], 0.5, 0, verts[6], 0, 0.25, verts[0], 1, 0.25); 52 | //centre 1vert top 53 | addIcosahedronTriangle(verts[0], 0.5, 0.25, verts[11],0, 0.75, verts[10],1, 0.75); 54 | addIcosahedronTriangle(verts[5], 0.5, 0.25, verts[10],0, 0.75, verts[4], 1, 0.75); 55 | addIcosahedronTriangle(verts[9], 0.5, 0.25, verts[4], 0, 0.75, verts[2], 1, 0.75); 56 | addIcosahedronTriangle(verts[8], 0.5, 0.25, verts[2], 0, 0.75, verts[7], 1, 0.75); 57 | addIcosahedronTriangle(verts[6], 0.5, 0.25, verts[7], 0, 0.75, verts[11],1, 0.75); 58 | //centre 1vert bottom 59 | addIcosahedronTriangle(verts[2], 0.5, 0.75, verts[8], 0, 0.25, verts[9], 1, 0.25); 60 | addIcosahedronTriangle(verts[7], 0.5, 0.75, verts[6], 0, 0.25, verts[8], 1, 0.25); 61 | addIcosahedronTriangle(verts[11],0.5, 0.75, verts[0], 0, 0.25, verts[6], 1, 0.25); 62 | addIcosahedronTriangle(verts[10],0.5, 0.75, verts[5], 0, 0.25, verts[0], 1, 0.25); 63 | addIcosahedronTriangle(verts[4], 0.5, 0.75, verts[9], 0, 0.25, verts[5], 1, 0.25); 64 | //bottom 65 | addIcosahedronTriangle(verts[3], 0.5, 1, verts[2], 0, 0.75, verts[4], 1, 0.75); 66 | addIcosahedronTriangle(verts[3], 0.5, 1, verts[7], 0, 0.75, verts[2], 1, 0.75); 67 | addIcosahedronTriangle(verts[3], 0.5, 1, verts[11],0, 0.75, verts[7], 1, 0.75); 68 | addIcosahedronTriangle(verts[3], 0.5, 1, verts[10],0, 0.75, verts[11],1, 0.75); 69 | addIcosahedronTriangle(verts[3], 0.5, 1, verts[4], 0, 0.75, verts[10],1, 0.75); 70 | 71 | icosahedron4.computeNormals().smoothNormals(); 72 | icosahedron7.computeNormals().smoothNormals(); 73 | } 74 | 75 | private static void addIcosahedronTriangle(Vector3 vec1, double u1, double v1, 76 | Vector3 vec2, double u2, double v2, 77 | Vector3 vec3, double u3, double v3) 78 | { 79 | icosahedron4.verts[i*3] = icosahedron7.verts[i*4] = new Vertex5(vec1, u1, v1); 80 | icosahedron4.verts[i*3+1] = icosahedron7.verts[i*4+1] = new Vertex5(vec2, u2, v2); 81 | icosahedron4.verts[i*3+2] = icosahedron7.verts[i*4+2] = icosahedron7.verts[i*4+3] = new Vertex5(vec3, u3, v3); 82 | i++; 83 | } 84 | 85 | public static Matrix4 getRenderMatrix(Vector3 position, Rotation rotation, double scale) 86 | { 87 | return new Matrix4().translate(position).apply(new Scale(scale)).apply(rotation); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/CCRenderPipeline.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import codechicken.lib.render.CCRenderState.IVertexOperation; 4 | import codechicken.lib.render.CCRenderState.VertexAttribute; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class CCRenderPipeline 9 | { 10 | public class PipelineBuilder 11 | { 12 | public PipelineBuilder add(IVertexOperation op) { 13 | ops.add(op); 14 | return this; 15 | } 16 | 17 | public PipelineBuilder add(IVertexOperation... ops) { 18 | for(int i = 0; i < ops.length; i++) 19 | CCRenderPipeline.this.ops.add(ops[i]); 20 | return this; 21 | } 22 | 23 | public void build() { 24 | rebuild(); 25 | } 26 | 27 | public void render() { 28 | rebuild(); 29 | CCRenderState.render(); 30 | } 31 | } 32 | 33 | private class PipelineNode 34 | { 35 | public ArrayList deps = new ArrayList(); 36 | public IVertexOperation op; 37 | 38 | public void add() { 39 | if(op == null) 40 | return; 41 | 42 | for(int i = 0; i < deps.size(); i++) 43 | deps.get(i).add(); 44 | deps.clear(); 45 | sorted.add(op); 46 | op = null; 47 | } 48 | } 49 | 50 | private ArrayList attribs = new ArrayList(); 51 | private ArrayList ops = new ArrayList(); 52 | private ArrayList nodes = new ArrayList(); 53 | private ArrayList sorted = new ArrayList(); 54 | private PipelineNode loading; 55 | private PipelineBuilder builder = new PipelineBuilder(); 56 | 57 | public void setPipeline(IVertexOperation... ops) { 58 | this.ops.clear(); 59 | for(int i = 0; i < ops.length; i++) 60 | this.ops.add(ops[i]); 61 | rebuild(); 62 | } 63 | 64 | public void reset() { 65 | ops.clear(); 66 | unbuild(); 67 | } 68 | 69 | private void unbuild() { 70 | for(int i = 0; i < attribs.size(); i++) 71 | attribs.get(i).active = false; 72 | attribs.clear(); 73 | sorted.clear(); 74 | } 75 | 76 | public void rebuild() { 77 | if(ops.isEmpty() || CCRenderState.model == null) 78 | return; 79 | 80 | //ensure enough nodes for all ops 81 | while(nodes.size() < CCRenderState.operationCount()) 82 | nodes.add(new PipelineNode()); 83 | unbuild(); 84 | 85 | if(CCRenderState.useNormals) 86 | addAttribute(CCRenderState.normalAttrib); 87 | if(CCRenderState.useColour) 88 | addAttribute(CCRenderState.colourAttrib); 89 | if(CCRenderState.computeLighting) 90 | addAttribute(CCRenderState.lightingAttrib); 91 | 92 | for(int i = 0; i < ops.size(); i++) { 93 | IVertexOperation op = ops.get(i); 94 | loading = nodes.get(op.operationID()); 95 | boolean loaded = op.load(); 96 | if(loaded) 97 | loading.op = op; 98 | 99 | if(op instanceof VertexAttribute) 100 | if(loaded) 101 | attribs.add((VertexAttribute)op); 102 | else 103 | ((VertexAttribute)op).active = false; 104 | } 105 | 106 | for(int i = 0; i < nodes.size(); i++) 107 | nodes.get(i).add(); 108 | } 109 | 110 | public void addRequirement(int opRef) { 111 | loading.deps.add(nodes.get(opRef)); 112 | } 113 | 114 | public void addDependency(VertexAttribute attrib) { 115 | loading.deps.add(nodes.get(attrib.operationID())); 116 | addAttribute(attrib); 117 | } 118 | 119 | public void addAttribute(VertexAttribute attrib) { 120 | if(!attrib.active) { 121 | ops.add(attrib); 122 | attrib.active = true; 123 | } 124 | } 125 | 126 | public void operate() { 127 | for(int i = 0; i < sorted.size(); i++) 128 | sorted.get(i).operate(); 129 | } 130 | 131 | public PipelineBuilder builder() { 132 | ops.clear(); 133 | return builder; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/ColourMultiplier.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import codechicken.lib.colour.ColourRGBA; 4 | 5 | public class ColourMultiplier implements CCRenderState.IVertexOperation 6 | { 7 | private static ColourMultiplier instance = new ColourMultiplier(-1); 8 | 9 | public static ColourMultiplier instance(int colour) { 10 | instance.colour = colour; 11 | return instance; 12 | } 13 | 14 | public static final int operationIndex = CCRenderState.registerOperation(); 15 | public int colour; 16 | 17 | public ColourMultiplier(int colour) { 18 | this.colour = colour; 19 | } 20 | 21 | @Override 22 | public boolean load() { 23 | if(colour == -1) return false; 24 | 25 | CCRenderState.pipeline.addDependency(CCRenderState.colourAttrib); 26 | return true; 27 | } 28 | 29 | @Override 30 | public void operate() { 31 | CCRenderState.setColour(ColourRGBA.multiply(CCRenderState.colour, colour)); 32 | } 33 | 34 | @Override 35 | public int operationID() { 36 | return operationIndex; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/EntityDigIconFX.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import codechicken.lib.vec.Cuboid6; 4 | import codechicken.lib.vec.Vector3; 5 | import net.minecraft.client.particle.EffectRenderer; 6 | import net.minecraft.client.particle.EntityFX; 7 | import net.minecraft.client.renderer.WorldRenderer; 8 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 9 | import net.minecraft.entity.Entity; 10 | import net.minecraft.world.World; 11 | 12 | public class EntityDigIconFX extends EntityFX 13 | { 14 | public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, TextureAtlasSprite icon) 15 | { 16 | super(world, x, y, z, dx, dy, dz); 17 | particleIcon = icon; 18 | particleGravity = 1; 19 | particleRed = particleGreen = particleBlue = 0.6F; 20 | particleScale /= 2.0F; 21 | } 22 | 23 | @Override 24 | public int getFXLayer() 25 | { 26 | return 1; 27 | } 28 | 29 | public void setScale(float scale) { 30 | particleScale = scale; 31 | } 32 | 33 | public float getScale() { 34 | return particleScale; 35 | } 36 | 37 | public void setMaxAge(int age){ 38 | particleMaxAge = age; 39 | } 40 | 41 | public int getMaxAge(){ 42 | return particleMaxAge; 43 | } 44 | 45 | /** 46 | * copy pasted from EntityDiggingFX 47 | */ 48 | @Override 49 | public void renderParticle(WorldRenderer par1Tessellator, Entity entity, float par2, float par3, float par4, float par5, float par6, float par7) 50 | { 51 | float f6 = (particleTextureIndexX + particleTextureJitterX / 4.0F) / 16.0F; 52 | float f7 = f6 + 0.015609375F; 53 | float f8 = (particleTextureIndexY + particleTextureJitterY / 4.0F) / 16.0F; 54 | float f9 = f8 + 0.015609375F; 55 | float f10 = 0.1F * particleScale; 56 | 57 | if (particleIcon != null) 58 | { 59 | f6 = particleIcon.getInterpolatedU(particleTextureJitterX / 4.0F * 16.0F); 60 | f7 = particleIcon.getInterpolatedU((particleTextureJitterX + 1.0F) / 4.0F * 16.0F); 61 | f8 = particleIcon.getInterpolatedV(particleTextureJitterY / 4.0F * 16.0F); 62 | f9 = particleIcon.getInterpolatedV((particleTextureJitterY + 1.0F) / 4.0F * 16.0F); 63 | } 64 | 65 | float f11 = (float)(prevPosX + (posX - prevPosX) * par2 - interpPosX); 66 | float f12 = (float)(prevPosY + (posY - prevPosY) * par2 - interpPosY); 67 | float f13 = (float)(prevPosZ + (posZ - prevPosZ) * par2 - interpPosZ); 68 | float f14 = 1.0F; 69 | 70 | par1Tessellator.pos(f11 - par3 * f10 - par6 * f10, f12 - par4 * f10, f13 - par5 * f10 - par7 * f10).tex(f6, f9).color(f14 * particleRed, f14 * particleGreen, f14 * particleBlue, 255F).endVertex(); 71 | par1Tessellator.pos(f11 - par3 * f10 + par6 * f10, f12 + par4 * f10, f13 - par5 * f10 + par7 * f10).tex(f6, f8).color(f14 * particleRed, f14 * particleGreen, f14 * particleBlue, 255F).endVertex(); 72 | par1Tessellator.pos(f11 + par3 * f10 + par6 * f10, f12 + par4 * f10, f13 + par5 * f10 + par7 * f10).tex(f7, f8).color(f14 * particleRed, f14 * particleGreen, f14 * particleBlue, 255F).endVertex(); 73 | par1Tessellator.pos(f11 + par3 * f10 - par6 * f10, f12 - par4 * f10, f13 + par5 * f10 - par7 * f10).tex(f7, f9).color(f14 * particleRed, f14 * particleGreen, f14 * particleBlue, 255F).endVertex(); 74 | } 75 | 76 | public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, TextureAtlasSprite icon, EffectRenderer effectRenderer) 77 | { 78 | float border = 0.1F; 79 | Vector3 diff = bounds.max.copy().subtract(bounds.min).add(-2*border); 80 | diff.x*=world.rand.nextDouble(); 81 | diff.y*=world.rand.nextDouble(); 82 | diff.z*=world.rand.nextDouble(); 83 | Vector3 pos = diff.add(bounds.min).add(border); 84 | 85 | if (side == 0) 86 | diff.y = bounds.min.y - border; 87 | if (side == 1) 88 | diff.y = bounds.max.y + border; 89 | if (side == 2) 90 | diff.z = bounds.min.z - border; 91 | if (side == 3) 92 | diff.z = bounds.max.z + border; 93 | if (side == 4) 94 | diff.x = bounds.min.x - border; 95 | if (side == 5) 96 | diff.x = bounds.max.x + border; 97 | 98 | effectRenderer.addEffect( 99 | new EntityDigIconFX(world, pos.x, pos.y, pos.z, 0, 0, 0, icon) 100 | .multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F)); 101 | } 102 | 103 | public static void addBlockDestroyEffects(World world, Cuboid6 bounds, TextureAtlasSprite[] icons, EffectRenderer effectRenderer) 104 | { 105 | Vector3 diff = bounds.max.copy().subtract(bounds.min); 106 | Vector3 center = bounds.min.copy().add(bounds.max).multiply(0.5); 107 | Vector3 density = diff.copy().multiply(4); 108 | density.x = Math.ceil(density.x); 109 | density.y = Math.ceil(density.y); 110 | density.z = Math.ceil(density.z); 111 | 112 | for (int i = 0; i < density.x; ++i) 113 | for (int j = 0; j < density.y; ++j) 114 | for (int k = 0; k < density.z; ++k) 115 | { 116 | double x = bounds.min.x+(i+0.5)*diff.x/density.x; 117 | double y = bounds.min.y+(j+0.5)*diff.y/density.y; 118 | double z = bounds.min.z+(k+0.5)*diff.z/density.z; 119 | effectRenderer.addEffect( 120 | new EntityDigIconFX(world, x, y, z, x-center.x, y-center.y, z-center.z, icons[world.rand.nextInt(icons.length)])); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/FontUtils.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.gui.FontRenderer; 5 | import net.minecraft.client.renderer.GlStateManager; 6 | import net.minecraft.item.ItemStack; 7 | 8 | public class FontUtils 9 | { 10 | public static FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj; 11 | 12 | public static void drawCenteredString(String s, int xCenter, int y, int colour) 13 | { 14 | fontRenderer.drawString(s, xCenter-fontRenderer.getStringWidth(s)/2, y, colour); 15 | } 16 | 17 | public static void drawRightString(String s, int xRight, int y, int colour) 18 | { 19 | fontRenderer.drawString(s, xRight-fontRenderer.getStringWidth(s), y, colour); 20 | } 21 | 22 | public static final String[] prefixes = new String[]{"K", "M", "G"}; 23 | public static void drawItemQuantity(int x, int y, ItemStack item, String quantity, int mode) 24 | { 25 | if(item == null || (quantity == null && item.stackSize <= 1)) 26 | return; 27 | 28 | if(quantity == null) 29 | { 30 | switch(mode) 31 | { 32 | case 2: 33 | int q = item.stackSize; 34 | String postfix = ""; 35 | for(int p = 0; p < 3 && q > 1000; p++) 36 | { 37 | q/=1000; 38 | postfix = prefixes[p]; 39 | } 40 | quantity = Integer.toString(q)+postfix; 41 | break; 42 | case 1: 43 | quantity = ""; 44 | if(item.stackSize/64 > 0) 45 | quantity+=item.stackSize/64 + "s"; 46 | if(item.stackSize%64 > 0) 47 | quantity+=item.stackSize%64; 48 | break; 49 | default: 50 | quantity = Integer.toString(item.stackSize); 51 | break; 52 | } 53 | } 54 | 55 | double scale = quantity.length() > 2 ? 0.5 : 1; 56 | double sheight = 8*scale; 57 | double swidth = fontRenderer.getStringWidth(quantity)*scale; 58 | 59 | GlStateManager.disableLighting(); 60 | GlStateManager.disableDepth(); 61 | GlStateManager.pushMatrix(); 62 | GlStateManager.translate(x + 16 - swidth, y + 16 - sheight, 0); 63 | GlStateManager.scale(scale, scale, 1); 64 | fontRenderer.drawStringWithShadow(quantity, 0, 0, 0xFFFFFF); 65 | GlStateManager.popMatrix(); 66 | GlStateManager.enableLighting(); 67 | GlStateManager.enableDepth(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/IFaceRenderer.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | public interface IFaceRenderer 4 | { 5 | public void renderFace(Vertex5[] face, int side); 6 | } 7 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/IItemRenderer.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import net.minecraft.client.resources.model.IBakedModel; 4 | import net.minecraft.item.ItemStack; 5 | 6 | /** 7 | * Hooks the location in RenderItem where TileEntityItemStackRenderer.renderByItem is called. 8 | * Be sure to override isBuiltInRenderer true 9 | */ 10 | public interface IItemRenderer extends IBakedModel 11 | { 12 | public void renderItem(ItemStack item); 13 | } 14 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/ManagedTextureFX.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | public class ManagedTextureFX extends TextureFX 4 | { 5 | public boolean changed; 6 | 7 | public ManagedTextureFX(int size, String name) 8 | { 9 | super(size, name); 10 | imageData = new int[size*size]; 11 | } 12 | 13 | @Override 14 | public void setup() 15 | { 16 | } 17 | 18 | public void setData(int[] data) 19 | { 20 | System.arraycopy(data, 0, imageData, 0, imageData.length); 21 | changed = true; 22 | } 23 | 24 | @Override 25 | public boolean changed() 26 | { 27 | boolean r = changed; 28 | changed = false; 29 | return r; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/ModelRegistryHelper.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.renderer.ItemMeshDefinition; 5 | import net.minecraft.client.resources.model.IBakedModel; 6 | import net.minecraft.client.resources.model.ModelResourceLocation; 7 | import net.minecraft.item.Item; 8 | import net.minecraft.item.ItemStack; 9 | import net.minecraft.util.ResourceLocation; 10 | import net.minecraftforge.client.event.ModelBakeEvent; 11 | import net.minecraftforge.common.MinecraftForge; 12 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 13 | import org.apache.commons.lang3.tuple.ImmutablePair; 14 | import org.apache.commons.lang3.tuple.Pair; 15 | 16 | import java.util.LinkedList; 17 | import java.util.List; 18 | 19 | public class ModelRegistryHelper 20 | { 21 | private static List> registerModels = new LinkedList>(); 22 | 23 | static { 24 | MinecraftForge.EVENT_BUS.register(new ModelRegistryHelper()); 25 | } 26 | 27 | public static void register(ModelResourceLocation location, IBakedModel model) { 28 | registerModels.add(new ImmutablePair(location, model)); 29 | } 30 | 31 | public static void registerItemModel(Item item, ResourceLocation location) { 32 | registerItemModel(item, 0, location); 33 | } 34 | 35 | public static void registerItemModel(Item item, int meta, ResourceLocation location) { 36 | Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(item, meta, new ModelResourceLocation(location, "inventory")); 37 | } 38 | 39 | public static void registerItemMesher(Item item, ItemMeshDefinition mesher) { 40 | Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(item, mesher); 41 | } 42 | 43 | public static void registerItemRenderer(Item item, IItemRenderer renderer, ResourceLocation location) { 44 | final ModelResourceLocation modelLoc = new ModelResourceLocation(location, "inventory"); 45 | register(modelLoc, renderer); 46 | registerItemMesher(item, new ItemMeshDefinition() { 47 | @Override 48 | public ModelResourceLocation getModelLocation(ItemStack stack) { 49 | return modelLoc; 50 | } 51 | }); 52 | } 53 | 54 | @SubscribeEvent 55 | public void onModelBake(ModelBakeEvent event) { 56 | for(Pair pair : registerModels) 57 | event.modelRegistry.putObject(pair.getKey(), pair.getValue()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/PlaceholderTexture.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 4 | import net.minecraft.client.resources.IResourceManager; 5 | import net.minecraft.util.ResourceLocation; 6 | 7 | public class PlaceholderTexture extends TextureAtlasSprite 8 | { 9 | protected PlaceholderTexture(String par1) { 10 | super(par1); 11 | } 12 | 13 | @Override 14 | public boolean hasCustomLoader(IResourceManager manager, ResourceLocation location) { 15 | return true; 16 | } 17 | 18 | @Override 19 | public boolean load(IResourceManager manager, ResourceLocation location) { 20 | return true; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/ShaderProgram.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import org.lwjgl.opengl.ARBShaderObjects; 4 | import org.lwjgl.opengl.ARBVertexShader; 5 | import org.lwjgl.opengl.GL11; 6 | import org.lwjgl.util.vector.Matrix4f; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.io.InputStreamReader; 12 | 13 | import static org.lwjgl.opengl.ARBShaderObjects.*; 14 | 15 | public class ShaderProgram 16 | { 17 | int programID; 18 | 19 | public ShaderProgram() 20 | { 21 | programID = glCreateProgramObjectARB(); 22 | if(programID == 0) 23 | throw new RuntimeException("Unable to allocate shader program object."); 24 | } 25 | 26 | public void attach(int shaderType, String resource) 27 | { 28 | InputStream stream = ShaderProgram.class.getResourceAsStream(resource); 29 | if(stream == null) 30 | throw new RuntimeException("Unable to locate resource: "+resource); 31 | 32 | attach(shaderType, stream); 33 | } 34 | 35 | public void use() 36 | { 37 | glUseProgramObjectARB(programID); 38 | } 39 | 40 | public static void restore() 41 | { 42 | glUseProgramObjectARB(0); 43 | } 44 | 45 | public void link() 46 | { 47 | glLinkProgramARB(programID); 48 | if(glGetObjectParameteriARB(programID, GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) 49 | throw new RuntimeException("Error linking program: "+getInfoLog(programID)); 50 | 51 | glValidateProgramARB(programID); 52 | if(glGetObjectParameteriARB(programID, GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) 53 | throw new RuntimeException("Error validating program: "+getInfoLog(programID)); 54 | 55 | use(); 56 | onLink(); 57 | restore(); 58 | } 59 | 60 | public void attach(int shaderType, InputStream stream) 61 | { 62 | if(stream == null) 63 | throw new RuntimeException("Invalid shader inputstream"); 64 | 65 | int shaderID = 0; 66 | try 67 | { 68 | shaderID = glCreateShaderObjectARB(shaderType); 69 | if(shaderID == 0) 70 | throw new RuntimeException("Unable to allocate shader object."); 71 | 72 | try 73 | { 74 | glShaderSourceARB(shaderID, asString(stream)); 75 | } 76 | catch(IOException e) 77 | { 78 | throw new RuntimeException("Error reading inputstream.", e); 79 | } 80 | 81 | glCompileShaderARB(shaderID); 82 | if(glGetObjectParameteriARB(shaderID, GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE) 83 | throw new RuntimeException("Error compiling shader: "+getInfoLog(shaderID)); 84 | 85 | glAttachObjectARB(programID, shaderID); 86 | } 87 | catch(RuntimeException e) 88 | { 89 | glDeleteObjectARB(shaderID); 90 | throw e; 91 | } 92 | } 93 | 94 | public static String asString(InputStream stream) throws IOException 95 | { 96 | StringBuilder sb = new StringBuilder(); 97 | BufferedReader bin = new BufferedReader(new InputStreamReader(stream)); 98 | String line; 99 | while((line = bin.readLine()) != null) 100 | sb.append(line).append('\n'); 101 | stream.close(); 102 | return sb.toString(); 103 | } 104 | 105 | private static String getInfoLog(int shaderID) 106 | { 107 | return glGetInfoLogARB(shaderID, glGetObjectParameteriARB(shaderID, GL_OBJECT_INFO_LOG_LENGTH_ARB)); 108 | } 109 | 110 | public int getUniformLoc(String name) 111 | { 112 | return ARBShaderObjects.glGetUniformLocationARB(programID, name); 113 | } 114 | 115 | public int getAttribLoc(String name) 116 | { 117 | return ARBVertexShader.glGetAttribLocationARB(programID, name); 118 | } 119 | 120 | public void uniformTexture(String name, int textureIndex) 121 | { 122 | ARBShaderObjects.glUniform1iARB(getUniformLoc(name), textureIndex); 123 | } 124 | 125 | public void onLink() 126 | { 127 | 128 | } 129 | 130 | public void glVertexAttributeMat4(int loc, Matrix4f matrix) 131 | { 132 | ARBVertexShader.glVertexAttrib4fARB(loc , matrix.m00, matrix.m01, matrix.m02, matrix.m03); 133 | ARBVertexShader.glVertexAttrib4fARB(loc+1, matrix.m10, matrix.m11, matrix.m12, matrix.m13); 134 | ARBVertexShader.glVertexAttrib4fARB(loc+2, matrix.m20, matrix.m21, matrix.m22, matrix.m23); 135 | ARBVertexShader.glVertexAttrib4fARB(loc+3, matrix.m30, matrix.m31, matrix.m32, matrix.m33); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/SpriteSheetManager.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import codechicken.lib.render.TextureUtils.IIconRegister; 4 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 5 | import net.minecraftforge.fml.relauncher.Side; 6 | import net.minecraftforge.fml.relauncher.SideOnly; 7 | import net.minecraft.client.renderer.texture.TextureMap; 8 | import net.minecraft.util.ResourceLocation; 9 | 10 | import java.util.ArrayList; 11 | import java.util.HashMap; 12 | 13 | public class SpriteSheetManager 14 | { 15 | @SideOnly(Side.CLIENT) 16 | public static class SpriteSheet implements IIconRegister 17 | { 18 | private int tilesX; 19 | private int tilesY; 20 | private ArrayList newSprites = new ArrayList(); 21 | private TextureSpecial[] sprites; 22 | private ResourceLocation resource; 23 | private TextureDataHolder texture; 24 | private int spriteWidth; 25 | private int spriteHeight; 26 | 27 | public int atlasIndex; 28 | 29 | private SpriteSheet(int tilesX, int tilesY, ResourceLocation textureFile) { 30 | this.tilesX = tilesX; 31 | this.tilesY = tilesY; 32 | this.resource = textureFile; 33 | sprites = new TextureSpecial[tilesX * tilesY]; 34 | } 35 | 36 | public void requestIndicies(int... indicies) { 37 | for (int i : indicies) 38 | setupSprite(i); 39 | } 40 | 41 | @Override 42 | public void registerIcons(TextureMap textureMap) { 43 | if (TextureUtils.refreshTexture(textureMap, resource.getResourcePath())) { 44 | reloadTexture(); 45 | for (TextureSpecial sprite : sprites) 46 | if (sprite != null) 47 | textureMap.setTextureEntry(sprite.getIconName(), sprite); 48 | } else { 49 | for (int i : newSprites) 50 | textureMap.setTextureEntry(sprites[i].getIconName(), sprites[i]); 51 | } 52 | newSprites.clear(); 53 | } 54 | 55 | public TextureSpecial setupSprite(int i) { 56 | if (sprites[i] == null) { 57 | String name = resource + "_" + i; 58 | sprites[i] = new TextureSpecial(name).baseFromSheet(this, i); 59 | newSprites.add(i); 60 | } 61 | return sprites[i]; 62 | } 63 | 64 | private void reloadTexture() { 65 | texture = TextureUtils.loadTexture(resource); 66 | spriteWidth = texture.width / tilesX; 67 | spriteHeight = texture.height / tilesY; 68 | } 69 | 70 | public TextureAtlasSprite getSprite(int index) { 71 | TextureAtlasSprite i = sprites[index]; 72 | if (i == null) 73 | throw new IllegalArgumentException("Sprite at index: " + index + " from texture file " + resource + " was not preloaded."); 74 | return i; 75 | } 76 | 77 | public TextureDataHolder createSprite(int spriteIndex) { 78 | int sx = spriteIndex % tilesX; 79 | int sy = spriteIndex / tilesX; 80 | TextureDataHolder sprite = new TextureDataHolder(spriteWidth, spriteHeight); 81 | TextureUtils.copySubImg(texture.data, texture.width, sx * spriteWidth, sy * spriteHeight, 82 | spriteWidth, spriteHeight, 83 | sprite.data, spriteWidth, 0, 0); 84 | return sprite; 85 | } 86 | 87 | public int spriteWidth() { 88 | return spriteWidth; 89 | } 90 | 91 | public int spriteHeight() { 92 | return spriteHeight; 93 | } 94 | 95 | public TextureSpecial bindTextureFX(int i, TextureFX textureFX) { 96 | return setupSprite(i).addTextureFX(textureFX); 97 | } 98 | 99 | public SpriteSheet selfRegister(int atlas) { 100 | TextureUtils.addIconRegister(this); 101 | return this; 102 | } 103 | } 104 | 105 | private static HashMap spriteSheets = new HashMap(); 106 | 107 | public static SpriteSheet getSheet(ResourceLocation resource) { 108 | return getSheet(16, 16, resource); 109 | } 110 | 111 | public static SpriteSheet getSheet(int tilesX, int tilesY, ResourceLocation resource) { 112 | SpriteSheet sheet = spriteSheets.get(resource.toString()); 113 | if (sheet == null) 114 | spriteSheets.put(resource.toString(), sheet = new SpriteSheet(tilesX, tilesY, resource)); 115 | return sheet; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/TextureDataHolder.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import java.awt.image.BufferedImage; 4 | 5 | public class TextureDataHolder 6 | { 7 | public int width; 8 | public int height; 9 | public int[] data; 10 | 11 | public TextureDataHolder(int width, int height) 12 | { 13 | this.width = width; 14 | this.height = height; 15 | data = new int[width*height]; 16 | } 17 | 18 | public TextureDataHolder(int[] data, int width) 19 | { 20 | this.data = data; 21 | this.width = width; 22 | height = data.length/width; 23 | } 24 | 25 | public TextureDataHolder(BufferedImage img) 26 | { 27 | this(img.getWidth(), img.getHeight()); 28 | img.getRGB(0, 0, width, height, data, 0, width); 29 | } 30 | 31 | public TextureDataHolder copyData() 32 | { 33 | int[] copy = new int[data.length]; 34 | System.arraycopy(data, 0, copy, 0, data.length); 35 | data = copy; 36 | return this; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/TextureFX.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import codechicken.lib.render.SpriteSheetManager.SpriteSheet; 4 | import net.minecraftforge.fml.relauncher.Side; 5 | import net.minecraftforge.fml.relauncher.SideOnly; 6 | import net.minecraft.client.Minecraft; 7 | 8 | @SideOnly(Side.CLIENT) 9 | public class TextureFX 10 | { 11 | public int[] imageData; 12 | public int tileSizeBase = 16; 13 | public int tileSizeSquare = 256; 14 | public int tileSizeMask = 15; 15 | public int tileSizeSquareMask = 255; 16 | 17 | public boolean anaglyphEnabled; 18 | public TextureSpecial texture; 19 | 20 | public TextureFX(int spriteIndex, SpriteSheet sheet) { 21 | texture = sheet.bindTextureFX(spriteIndex, this); 22 | } 23 | 24 | public TextureFX(int size, String name) { 25 | texture = new TextureSpecial(name).blank(size).selfRegister().addTextureFX(this); 26 | } 27 | 28 | public TextureFX setAtlas(int index) { 29 | texture.atlasIndex = index; 30 | return this; 31 | } 32 | 33 | public void setup() { 34 | imageData = new int[tileSizeSquare]; 35 | } 36 | 37 | public void onTextureDimensionsUpdate(int width, int height) { 38 | if (width != height) 39 | throw new IllegalArgumentException("Non-Square textureFX not supported (" + width + ":" + height + ")"); 40 | 41 | tileSizeBase = width; 42 | tileSizeSquare = tileSizeBase * tileSizeBase; 43 | tileSizeMask = tileSizeBase - 1; 44 | tileSizeSquareMask = tileSizeSquare - 1; 45 | setup(); 46 | } 47 | 48 | public void update() { 49 | anaglyphEnabled = Minecraft.getMinecraft().gameSettings.anaglyph; 50 | onTick(); 51 | } 52 | 53 | public void onTick() { 54 | } 55 | 56 | public boolean changed() { 57 | return true; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/TextureUtils.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import codechicken.lib.colour.Colour; 4 | import codechicken.lib.colour.ColourARGB; 5 | import net.minecraft.client.renderer.GlStateManager; 6 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 7 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 8 | import net.minecraft.client.Minecraft; 9 | import net.minecraft.client.renderer.texture.TextureMap; 10 | import net.minecraft.util.ResourceLocation; 11 | import net.minecraftforge.client.event.TextureStitchEvent; 12 | import net.minecraftforge.common.MinecraftForge; 13 | import org.lwjgl.opengl.GL11; 14 | import org.lwjgl.opengl.GL12; 15 | 16 | import javax.imageio.ImageIO; 17 | import java.awt.image.BufferedImage; 18 | import java.io.IOException; 19 | import java.io.InputStream; 20 | import java.util.ArrayList; 21 | 22 | public class TextureUtils 23 | { 24 | public static interface IIconRegister 25 | { 26 | public void registerIcons(TextureMap textureMap); 27 | } 28 | 29 | static { 30 | MinecraftForge.EVENT_BUS.register(new TextureUtils()); 31 | } 32 | 33 | private static ArrayList iconRegisters = new ArrayList(); 34 | 35 | public static void addIconRegister(IIconRegister registrar) { 36 | iconRegisters.add(registrar); 37 | } 38 | 39 | @SubscribeEvent 40 | public void textureLoad(TextureStitchEvent.Pre event) { 41 | for (IIconRegister reg : iconRegisters) 42 | reg.registerIcons(event.map); 43 | } 44 | 45 | /** 46 | * @return an array of ARGB pixel data 47 | */ 48 | public static int[] loadTextureData(ResourceLocation resource) { 49 | return loadTexture(resource).data; 50 | } 51 | 52 | public static Colour[] loadTextureColours(ResourceLocation resource) { 53 | int[] idata = loadTextureData(resource); 54 | Colour[] data = new Colour[idata.length]; 55 | for (int i = 0; i < data.length; i++) 56 | data[i] = new ColourARGB(idata[i]); 57 | return data; 58 | } 59 | 60 | public static InputStream getTextureResource(ResourceLocation textureFile) throws IOException { 61 | return Minecraft.getMinecraft().getResourceManager().getResource(textureFile).getInputStream(); 62 | } 63 | 64 | public static BufferedImage loadBufferedImage(ResourceLocation textureFile) { 65 | try { 66 | return loadBufferedImage(getTextureResource(textureFile)); 67 | } catch (Exception e) { 68 | System.err.println("Failed to load texture file: " + textureFile); 69 | e.printStackTrace(); 70 | } 71 | return null; 72 | } 73 | 74 | public static BufferedImage loadBufferedImage(InputStream in) throws IOException { 75 | BufferedImage img = ImageIO.read(in); 76 | in.close(); 77 | return img; 78 | } 79 | 80 | public static void copySubImg(int[] fromTex, int fromWidth, int fromX, int fromY, int width, int height, int[] toTex, int toWidth, int toX, int toY) { 81 | for (int y = 0; y < height; y++) 82 | for (int x = 0; x < width; x++) { 83 | int fp = (y + fromY) * fromWidth + x + fromX; 84 | int tp = (y + toX) * toWidth + x + toX; 85 | 86 | toTex[tp] = fromTex[fp]; 87 | } 88 | } 89 | 90 | public static TextureAtlasSprite getBlankIcon(int size, TextureMap textureMap) { 91 | String s = "blank_" + size; 92 | TextureAtlasSprite icon = textureMap.getTextureExtry(s); 93 | if (icon == null) 94 | textureMap.setTextureEntry(s, icon = new TextureSpecial(s).blank(size)); 95 | 96 | return icon; 97 | } 98 | 99 | public static TextureSpecial getTextureSpecial(TextureMap textureMap, String name) { 100 | if (textureMap.getTextureExtry(name) != null) 101 | throw new IllegalStateException("Texture: " + name + " is already registered"); 102 | 103 | TextureSpecial icon = new TextureSpecial(name); 104 | textureMap.setTextureEntry(name, icon); 105 | return icon; 106 | } 107 | 108 | public static void prepareTexture(int target, int texture, int min_mag_filter, int wrap) { 109 | GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, min_mag_filter); 110 | GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, min_mag_filter); 111 | if(target == GL11.GL_TEXTURE_2D) 112 | GlStateManager.bindTexture(target); 113 | else 114 | GL11.glBindTexture(target, texture); 115 | 116 | switch (target) { 117 | case GL12.GL_TEXTURE_3D: 118 | GL11.glTexParameteri(target, GL12.GL_TEXTURE_WRAP_R, wrap); 119 | case GL11.GL_TEXTURE_2D: 120 | GL11.glTexParameteri(target, GL11.GL_TEXTURE_WRAP_T, wrap); 121 | case GL11.GL_TEXTURE_1D: 122 | GL11.glTexParameteri(target, GL11.GL_TEXTURE_WRAP_S, wrap); 123 | } 124 | } 125 | 126 | public static TextureDataHolder loadTexture(ResourceLocation resource) { 127 | BufferedImage img = loadBufferedImage(resource); 128 | if (img == null) 129 | throw new RuntimeException("Texture not found: " + resource); 130 | return new TextureDataHolder(img); 131 | } 132 | 133 | /** 134 | * Uses an empty placeholder texture to tell if the map has been reloaded since the last call to refresh texture and the texture with name needs to be reacquired to be valid 135 | */ 136 | public static boolean refreshTexture(TextureMap map, String name) { 137 | if (map.getTextureExtry(name) == null) { 138 | map.setTextureEntry(name, new PlaceholderTexture(name)); 139 | return true; 140 | } 141 | return false; 142 | } 143 | 144 | /*public static IIcon safeIcon(IIcon icon) { 145 | if (icon == null) 146 | icon = ((TextureMap) Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).getAtlasSprite("missingno"); 147 | 148 | return icon; 149 | }*/ 150 | } 151 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/Vertex5.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render; 2 | 3 | import codechicken.lib.render.uv.UV; 4 | import codechicken.lib.render.uv.UVTransformation; 5 | import codechicken.lib.util.Copyable; 6 | import codechicken.lib.vec.Transformation; 7 | import codechicken.lib.vec.Vector3; 8 | 9 | import java.math.BigDecimal; 10 | import java.math.MathContext; 11 | import java.math.RoundingMode; 12 | 13 | public class Vertex5 implements Copyable 14 | { 15 | public Vector3 vec; 16 | public UV uv; 17 | 18 | public Vertex5() { 19 | this(new Vector3(), new UV()); 20 | } 21 | 22 | public Vertex5(Vector3 vert, UV uv) { 23 | this.vec = vert; 24 | this.uv = uv; 25 | } 26 | 27 | public Vertex5(Vector3 vert, double u, double v) { 28 | this(vert, new UV(u, v)); 29 | } 30 | 31 | public Vertex5(double x, double y, double z, double u, double v) { 32 | this(x, y, z, u, v, 0); 33 | } 34 | 35 | public Vertex5(double x, double y, double z, double u, double v, int tex) { 36 | this(new Vector3(x, y, z), new UV(u, v, tex)); 37 | } 38 | 39 | public Vertex5 set(double x, double y, double z, double u, double v) { 40 | vec.set(x, y, z); 41 | uv.set(u, v); 42 | return this; 43 | } 44 | 45 | public Vertex5 set(double x, double y, double z, double u, double v, int tex) { 46 | vec.set(x, y, z); 47 | uv.set(u, v, tex); 48 | return this; 49 | } 50 | 51 | public Vertex5 set(Vertex5 vert) { 52 | vec.set(vert.vec); 53 | uv.set(vert.uv); 54 | return this; 55 | } 56 | 57 | public Vertex5(Vertex5 vertex5) { 58 | this(vertex5.vec.copy(), vertex5.uv.copy()); 59 | } 60 | 61 | public Vertex5 copy() { 62 | return new Vertex5(this); 63 | } 64 | 65 | public String toString() { 66 | MathContext cont = new MathContext(4, RoundingMode.HALF_UP); 67 | return "Vertex: (" + new BigDecimal(vec.x, cont) + ", " + new BigDecimal(vec.y, cont) + ", " + new BigDecimal(vec.z, cont) + ") " + 68 | "(" + new BigDecimal(uv.u, cont) + ", " + new BigDecimal(uv.v, cont) + ") ("+uv.tex+")"; 69 | } 70 | 71 | public Vertex5 apply(Transformation t) { 72 | vec.apply(t); 73 | return this; 74 | } 75 | 76 | public Vertex5 apply(UVTransformation t) { 77 | uv.apply(t); 78 | return this; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/uv/IconTransformation.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render.uv; 2 | 3 | import codechicken.lib.vec.IrreversibleTransformationException; 4 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 5 | 6 | public class IconTransformation extends UVTransformation { 7 | public TextureAtlasSprite icon; 8 | 9 | public IconTransformation(TextureAtlasSprite icon) { 10 | this.icon = icon; 11 | } 12 | 13 | @Override 14 | public void apply(UV uv) { 15 | uv.u = icon.getInterpolatedU(uv.u * 16); 16 | uv.v = icon.getInterpolatedV(uv.v * 16); 17 | } 18 | 19 | @Override 20 | public UVTransformation inverse() { 21 | throw new IrreversibleTransformationException(this); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/uv/MultiIconTransformation.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render.uv; 2 | 3 | import codechicken.lib.vec.IrreversibleTransformationException; 4 | import net.minecraft.client.renderer.texture.TextureAtlasSprite; 5 | 6 | public class MultiIconTransformation extends UVTransformation { 7 | public TextureAtlasSprite[] icons; 8 | 9 | public MultiIconTransformation(TextureAtlasSprite... icons) { 10 | this.icons = icons; 11 | } 12 | 13 | @Override 14 | public void apply(UV uv) { 15 | TextureAtlasSprite icon = icons[uv.tex % icons.length]; 16 | uv.u = icon.getInterpolatedU(uv.u * 16); 17 | uv.v = icon.getInterpolatedV(uv.v * 16); 18 | } 19 | 20 | @Override 21 | public UVTransformation inverse() { 22 | throw new IrreversibleTransformationException(this); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/uv/UV.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render.uv; 2 | 3 | import codechicken.lib.util.Copyable; 4 | 5 | import java.math.BigDecimal; 6 | import java.math.MathContext; 7 | import java.math.RoundingMode; 8 | 9 | public class UV implements Copyable { 10 | public double u; 11 | public double v; 12 | public int tex; 13 | 14 | public UV() { 15 | } 16 | 17 | public UV(double u, double v) { 18 | this(u, v, 0); 19 | } 20 | 21 | public UV(double u, double v, int tex) { 22 | this.u = u; 23 | this.v = v; 24 | this.tex = tex; 25 | } 26 | 27 | public UV(UV uv) { 28 | this(uv.u, uv.v, uv.tex); 29 | } 30 | 31 | public UV set(double u, double v, int tex) { 32 | this.u = u; 33 | this.v = v; 34 | this.tex = tex; 35 | return this; 36 | } 37 | 38 | public UV set(double u, double v) { 39 | return set(u, v, tex); 40 | } 41 | 42 | public UV set(UV uv) { 43 | return set(uv.u, uv.v, uv.tex); 44 | } 45 | 46 | public UV copy() { 47 | return new UV(this); 48 | } 49 | 50 | public UV add(UV uv) { 51 | u += uv.u; 52 | v += uv.v; 53 | return this; 54 | } 55 | 56 | public UV multiply(double d) { 57 | u *= d; 58 | v *= d; 59 | return this; 60 | } 61 | 62 | public String toString() { 63 | MathContext cont = new MathContext(4, RoundingMode.HALF_UP); 64 | return "UV(" + new BigDecimal(u, cont) + ", " + new BigDecimal(v, cont) + ")"; 65 | } 66 | 67 | public UV apply(UVTransformation t) { 68 | t.apply(this); 69 | return this; 70 | } 71 | 72 | @Override 73 | public boolean equals(Object o) { 74 | if (!(o instanceof UV)) 75 | return false; 76 | UV uv = (UV) o; 77 | return u == uv.u && v == uv.v; 78 | } 79 | } -------------------------------------------------------------------------------- /src/codechicken/lib/render/uv/UVRotation.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render.uv; 2 | 3 | import codechicken.lib.math.MathHelper; 4 | 5 | import java.math.BigDecimal; 6 | import java.math.MathContext; 7 | import java.math.RoundingMode; 8 | 9 | public class UVRotation extends UVTransformation 10 | { 11 | public double angle; 12 | 13 | /** 14 | * @param angle The angle to rotate counterclockwise in radians 15 | */ 16 | public UVRotation(double angle) { 17 | this.angle = angle; 18 | } 19 | 20 | @Override 21 | public void apply(UV uv) { 22 | double c = MathHelper.cos(angle); 23 | double s = MathHelper.sin(angle); 24 | double u2 = c*uv.u + s*uv.v; 25 | uv.v = - s*uv.u + c*uv.v; 26 | uv.u = u2; 27 | } 28 | 29 | @Override 30 | public UVTransformation inverse() { 31 | return new UVRotation(-angle); 32 | } 33 | 34 | @Override 35 | public UVTransformation merge(UVTransformation next) { 36 | if(next instanceof UVRotation) 37 | return new UVRotation(angle+((UVRotation)next).angle); 38 | 39 | return null; 40 | } 41 | 42 | @Override 43 | public boolean isRedundant() { 44 | return MathHelper.between(-1E-5, angle, 1E-5); 45 | } 46 | 47 | @Override 48 | public String toString() 49 | { 50 | MathContext cont = new MathContext(4, RoundingMode.HALF_UP); 51 | return "UVRotation(" + new BigDecimal(angle, cont) + ")"; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/uv/UVScale.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render.uv; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.MathContext; 5 | import java.math.RoundingMode; 6 | 7 | public class UVScale extends UVTransformation { 8 | double su; 9 | double sv; 10 | 11 | public UVScale(double scaleu, double scalev) { 12 | su = scaleu; 13 | sv = scalev; 14 | } 15 | 16 | public UVScale(double d) { 17 | this(d, d); 18 | } 19 | 20 | @Override 21 | public void apply(UV uv) { 22 | uv.u *= su; 23 | uv.v *= sv; 24 | } 25 | 26 | @Override 27 | public UVTransformation inverse() { 28 | return new UVScale(1 / su, 1 / sv); 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | MathContext cont = new MathContext(4, RoundingMode.HALF_UP); 34 | return "UVScale(" + new BigDecimal(su, cont) + ", " + new BigDecimal(sv, cont) + ")"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/uv/UVTransformation.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render.uv; 2 | 3 | import codechicken.lib.render.CCRenderState; 4 | import codechicken.lib.vec.ITransformation; 5 | 6 | /** 7 | * Abstract supertype for any UV transformation 8 | */ 9 | public abstract class UVTransformation extends ITransformation implements CCRenderState.IVertexOperation 10 | { 11 | public static final int operationIndex = CCRenderState.registerOperation(); 12 | 13 | public UVTransformation at(UV point) { 14 | return new UVTransformationList(new UVTranslation(-point.u, -point.v), this, new UVTranslation(point.u, point.v)); 15 | } 16 | 17 | public UVTransformationList with(UVTransformation t) { 18 | return new UVTransformationList(this, t); 19 | } 20 | 21 | @Override 22 | public boolean load() { 23 | return !isRedundant(); 24 | } 25 | 26 | @Override 27 | public void operate() { 28 | apply(CCRenderState.vert.uv); 29 | } 30 | 31 | @Override 32 | public int operationID() { 33 | return operationIndex; 34 | } 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/uv/UVTransformationList.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render.uv; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | 6 | public class UVTransformationList extends UVTransformation 7 | { 8 | private ArrayList transformations = new ArrayList(); 9 | 10 | public UVTransformationList(UVTransformation... transforms) 11 | { 12 | for(UVTransformation t : transforms) 13 | if(t instanceof UVTransformationList) 14 | transformations.addAll(((UVTransformationList)t).transformations); 15 | else 16 | transformations.add(t); 17 | 18 | compact(); 19 | } 20 | 21 | @Override 22 | public void apply(UV uv) 23 | { 24 | for(int i = 0; i < transformations.size(); i++) 25 | transformations.get(i).apply(uv); 26 | } 27 | 28 | @Override 29 | public UVTransformationList with(UVTransformation t) 30 | { 31 | if(t.isRedundant()) 32 | return this; 33 | 34 | if(t instanceof UVTransformationList) 35 | transformations.addAll(((UVTransformationList)t).transformations); 36 | else 37 | transformations.add(t); 38 | 39 | compact(); 40 | return this; 41 | } 42 | 43 | public UVTransformationList prepend(UVTransformation t) 44 | { 45 | if(t.isRedundant()) 46 | return this; 47 | 48 | if(t instanceof UVTransformationList) 49 | transformations.addAll(0, ((UVTransformationList)t).transformations); 50 | else 51 | transformations.add(0, t); 52 | 53 | compact(); 54 | return this; 55 | } 56 | 57 | private void compact() { 58 | ArrayList newList = new ArrayList(transformations.size()); 59 | Iterator iterator = transformations.iterator(); 60 | UVTransformation prev = null; 61 | while(iterator.hasNext()) { 62 | UVTransformation t = iterator.next(); 63 | if(t.isRedundant()) 64 | continue; 65 | 66 | if(prev != null) { 67 | UVTransformation m = prev.merge(t); 68 | if(m == null) 69 | newList.add(prev); 70 | else if(m.isRedundant()) 71 | t = null; 72 | else 73 | t = m; 74 | } 75 | prev = t; 76 | } 77 | if(prev != null) 78 | newList.add(prev); 79 | 80 | if(newList.size() < transformations.size()) 81 | transformations = newList; 82 | } 83 | 84 | @Override 85 | public boolean isRedundant() { 86 | return transformations.size() == 0; 87 | } 88 | 89 | @Override 90 | public UVTransformation inverse() 91 | { 92 | UVTransformationList rev = new UVTransformationList(); 93 | for(int i = transformations.size()-1; i >= 0; i--) 94 | rev.with(transformations.get(i).inverse()); 95 | return rev; 96 | } 97 | 98 | @Override 99 | public String toString() 100 | { 101 | String s = ""; 102 | for(UVTransformation t : transformations) 103 | s+="\n"+t.toString(); 104 | return s.trim(); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/codechicken/lib/render/uv/UVTranslation.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.render.uv; 2 | 3 | import codechicken.lib.math.MathHelper; 4 | 5 | import java.math.BigDecimal; 6 | import java.math.MathContext; 7 | import java.math.RoundingMode; 8 | 9 | public class UVTranslation extends UVTransformation { 10 | public double du; 11 | public double dv; 12 | 13 | public UVTranslation(double u, double v) { 14 | du = u; 15 | dv = v; 16 | } 17 | 18 | @Override 19 | public void apply(UV uv) { 20 | uv.u += du; 21 | uv.v += dv; 22 | } 23 | 24 | @Override 25 | public UVTransformation at(UV point) { 26 | return this; 27 | } 28 | 29 | @Override 30 | public UVTransformation inverse() { 31 | return new UVTranslation(-du, -dv); 32 | } 33 | 34 | @Override 35 | public UVTransformation merge(UVTransformation next) { 36 | if (next instanceof UVTranslation) { 37 | UVTranslation t = (UVTranslation)next; 38 | return new UVTranslation(du+t.du, dv+t.dv); 39 | } 40 | 41 | return null; 42 | } 43 | 44 | @Override 45 | public boolean isRedundant() { 46 | return MathHelper.between(-1E-5, du, 1E-5) && MathHelper.between(-1E-5, dv, 1E-5); 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | MathContext cont = new MathContext(4, RoundingMode.HALF_UP); 52 | return "UVTranslation(" + new BigDecimal(du, cont) + ", " + new BigDecimal(dv, cont) + ")"; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/codechicken/lib/tool/LibDownloader.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.tool; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.InputStream; 6 | import java.lang.reflect.Method; 7 | import java.net.URL; 8 | import java.net.URLClassLoader; 9 | import java.net.URLConnection; 10 | import java.nio.ByteBuffer; 11 | import java.util.LinkedList; 12 | import java.util.List; 13 | 14 | public class LibDownloader 15 | { 16 | private static String[] libs = new String[] { 17 | "org/ow2/asm/asm-debug-all/5.0.3/asm-debug-all-5.0.3.jar", 18 | "com/google/guava/guava/14.0/guava-14.0.jar", 19 | "net/sf/jopt-simple/jopt-simple/4.5/jopt-simple-4.5.jar", 20 | "org/apache/logging/log4j/log4j-core/2.0-beta9/log4j-core-2.0-beta9.jar", 21 | "org/apache/logging/log4j/log4j-api/2.0-beta9/log4j-api-2.0-beta9.jar"}; 22 | private static File libDir = new File("lib"); 23 | 24 | private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23); 25 | 26 | public static void load() { 27 | if(!libDir.exists()) 28 | libDir.mkdir(); 29 | if(!libDir.isDirectory()) 30 | throw new RuntimeException("/lib is not a directory"); 31 | 32 | List missing = checkExists(); 33 | for(String lib : missing) 34 | download(lib); 35 | addPaths(libs); 36 | } 37 | 38 | private static void addPaths(String[] libs) { 39 | try { 40 | URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader(); 41 | Method m_addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class}); 42 | m_addURL.setAccessible(true); 43 | for(String lib : libs) 44 | m_addURL.invoke(cl, new File(libDir, fileName(lib)).toURI().toURL()); 45 | } 46 | catch (Exception e) { 47 | throw new RuntimeException("Failed to add libraries to classpath", e); 48 | } 49 | } 50 | 51 | private static void download(String lib) { 52 | File libFile = new File(libDir, fileName(lib)); 53 | try 54 | { 55 | URL libDownload = new URL("http://repo1.maven.org/maven2/"+lib); 56 | URLConnection connection = libDownload.openConnection(); 57 | connection.setConnectTimeout(5000); 58 | connection.setReadTimeout(5000); 59 | connection.setRequestProperty("User-Agent", "CodeChickenLib Downloader"); 60 | int sizeGuess = connection.getContentLength(); 61 | download(connection.getInputStream(), sizeGuess, libFile); 62 | } 63 | catch (Exception e) 64 | { 65 | libFile.delete(); 66 | throw new RuntimeException("A download error occured", e); 67 | } 68 | } 69 | 70 | private static void download(InputStream is, int sizeGuess, File target) throws Exception 71 | { 72 | String name = target.getName(); 73 | if (sizeGuess > downloadBuffer.capacity()) 74 | throw new Exception(String.format("The file %s is too large to be downloaded", name)); 75 | 76 | downloadBuffer.clear(); 77 | 78 | int bytesRead, fullLength = 0; 79 | 80 | System.out.format("Downloading lib %s", name); 81 | byte[] smallBuffer = new byte[1024]; 82 | while ((bytesRead = is.read(smallBuffer)) >= 0) { 83 | downloadBuffer.put(smallBuffer, 0, bytesRead); 84 | fullLength += bytesRead; 85 | System.out.format("\rDownloading lib %s %d%%", name, (int) (fullLength * 100 / sizeGuess)); 86 | } 87 | System.out.format("\rDownloaded lib %s \n", name); 88 | is.close(); 89 | downloadBuffer.limit(fullLength); 90 | 91 | if(!target.exists()) 92 | target.createNewFile(); 93 | 94 | downloadBuffer.position(0); 95 | FileOutputStream fos = new FileOutputStream(target); 96 | fos.getChannel().write(downloadBuffer); 97 | fos.close(); 98 | } 99 | 100 | private static String fileName(String lib) { 101 | return lib.replaceAll(".+/", ""); 102 | } 103 | 104 | private static List checkExists() { 105 | LinkedList list = new LinkedList(); 106 | for(String lib : libs) { 107 | File file = new File(libDir, fileName(lib)); 108 | if(!file.exists()) 109 | list.add(lib); 110 | } 111 | return list; 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/codechicken/lib/tool/MCStripTransformer.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.tool; 2 | 3 | import codechicken.lib.asm.ASMHelper; 4 | import org.objectweb.asm.ClassReader; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | import org.objectweb.asm.commons.Remapper; 8 | import org.objectweb.asm.commons.RemappingMethodAdapter; 9 | import org.objectweb.asm.tree.ClassNode; 10 | import org.objectweb.asm.tree.MethodNode; 11 | 12 | import java.util.Iterator; 13 | 14 | public class MCStripTransformer { 15 | public static class ReferenceDetector extends Remapper { 16 | boolean found = false; 17 | 18 | @Override 19 | public String map(String typeName) { 20 | if(typeName.startsWith("net/minecraft") || !typeName.contains("/")) 21 | found = true; 22 | return typeName; 23 | } 24 | } 25 | 26 | public static byte[] transform(byte[] bytes) { 27 | ClassNode cnode = ASMHelper.createClassNode(bytes, ClassReader.EXPAND_FRAMES); 28 | 29 | boolean changed = false; 30 | Iterator it = cnode.methods.iterator(); 31 | while(it.hasNext()) { 32 | MethodNode mnode = it.next(); 33 | ReferenceDetector r = new ReferenceDetector(); 34 | mnode.accept(new RemappingMethodAdapter(mnode.access, mnode.desc, new MethodVisitor(Opcodes.ASM4) {}, r)); 35 | if(r.found) { 36 | it.remove(); 37 | changed = true; 38 | } 39 | } 40 | if(changed) 41 | bytes = ASMHelper.createBytes(cnode, 0); 42 | return bytes; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/codechicken/lib/tool/Main.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.tool; 2 | 3 | public class Main 4 | { 5 | public static void main(String[] args) { 6 | LibDownloader.load(); 7 | try { 8 | Class c_toolMain = new StripClassLoader().loadClass("codechicken.lib.tool.ToolMain"); 9 | c_toolMain.getDeclaredMethod("main", String[].class).invoke(null, new Object[]{args}); 10 | } catch (Exception e) { 11 | throw new RuntimeException(e); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/codechicken/lib/tool/StripClassLoader.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.tool; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.net.URL; 7 | import java.net.URLClassLoader; 8 | 9 | public class StripClassLoader extends URLClassLoader 10 | { 11 | public StripClassLoader() { 12 | super(new URL[0], StripClassLoader.class.getClassLoader()); 13 | } 14 | 15 | @Override 16 | public Class loadClass(String name) throws ClassNotFoundException { 17 | if(!name.startsWith("codechicken.lib")) 18 | return super.loadClass(name); 19 | 20 | try { 21 | String resName = name.replace('.', '/')+".class"; 22 | InputStream res = getResourceAsStream(resName); 23 | if(res == null) 24 | throw new ClassNotFoundException("Could not find resource: "+resName); 25 | byte[] bytes = readFully(res); 26 | bytes = transform(bytes); 27 | return defineClass(name, bytes, 0, bytes.length); 28 | 29 | } catch(IOException e) { 30 | throw new ClassNotFoundException(name, e); 31 | } 32 | } 33 | 34 | public static byte[] readFully(InputStream is) throws IOException { 35 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 36 | 37 | int read; 38 | byte[] data = new byte[16384]; 39 | while ((read = is.read(data, 0, data.length)) > 0) 40 | buffer.write(data, 0, read); 41 | 42 | return buffer.toByteArray(); 43 | } 44 | 45 | private byte[] transform(byte[] bytes) { 46 | 47 | bytes = MCStripTransformer.transform(bytes); 48 | return bytes; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/codechicken/lib/tool/ToolMain.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.tool; 2 | 3 | import codechicken.lib.tool.module.ModuleQBConverter; 4 | 5 | public class ToolMain 6 | { 7 | public static interface Module { 8 | public void main(String[] args); 9 | public String name(); 10 | public void printHelp(); 11 | } 12 | 13 | public static Module[] modules = new Module[]{ 14 | new ModuleQBConverter() 15 | }; 16 | 17 | private static void printHelp() { 18 | System.out.println("Usage: [module] [args]"); 19 | System.out.println(" Modules: "); 20 | for(Module m : modules) 21 | System.out.println(" - "+m.name()); 22 | System.out.println("-h [module] for module help"); 23 | } 24 | 25 | public static void main(String[] args) { 26 | if(args.length > 0) { 27 | for(Module m : modules) 28 | if(args[0].equals(m.name())) { 29 | String[] args2 = new String[args.length-1]; 30 | System.arraycopy(args, 1, args2, 0, args2.length); 31 | m.main(args2); 32 | return; 33 | } 34 | if(args[0].equals("-h") && args.length >= 2) { 35 | for(Module m : modules) 36 | if(args[1].equals(m.name())) { 37 | m.printHelp(); 38 | return; 39 | } 40 | } 41 | } 42 | printHelp(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/codechicken/lib/tool/module/JOptModule.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.tool.module; 2 | 3 | import codechicken.lib.tool.ToolMain; 4 | import joptsimple.OptionException; 5 | import joptsimple.OptionParser; 6 | import joptsimple.OptionSet; 7 | 8 | import java.io.IOException; 9 | 10 | public abstract class JOptModule implements ToolMain.Module 11 | { 12 | OptionParser parser = new OptionParser(); 13 | 14 | @Override 15 | public void main(String[] args) { 16 | OptionSet options; 17 | try 18 | { 19 | options = parser.parse(args); 20 | } 21 | catch(OptionException ex) 22 | { 23 | System.err.println(ex.getLocalizedMessage()); 24 | System.exit(-1); 25 | return; 26 | } 27 | 28 | try 29 | { 30 | main(parser, options); 31 | } 32 | catch(Exception e) 33 | { 34 | throw new RuntimeException(e); 35 | } 36 | } 37 | 38 | protected abstract void main(OptionParser parser, OptionSet options); 39 | 40 | @Override 41 | public void printHelp() { 42 | try { 43 | parser.printHelpOn(System.out); 44 | } catch (IOException e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/codechicken/lib/tool/module/ModuleQBConverter.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.tool.module; 2 | 3 | import codechicken.lib.render.QBImporter; 4 | import joptsimple.OptionParser; 5 | import joptsimple.OptionSet; 6 | 7 | import java.io.File; 8 | 9 | import static java.util.Arrays.asList; 10 | 11 | public class ModuleQBConverter extends JOptModule 12 | { 13 | public ModuleQBConverter() { 14 | parser.acceptsAll(asList("?", "h", "help"), "Show the help"); 15 | parser.acceptsAll(asList("i", "input"), "comma separated list of paths to models (.qb or directories)") 16 | .withRequiredArg().ofType(File.class).withValuesSeparatedBy(',').required(); 17 | parser.acceptsAll(asList("o", "out"), "Output Directory") 18 | .withRequiredArg().ofType(File.class); 19 | parser.acceptsAll(asList("o2", "textureplanes"), "2nd level optimisation. Merges coplanar polygons. Increases texture size"); 20 | parser.acceptsAll(asList("s", "squaretextures"), "Produce square textures"); 21 | parser.acceptsAll(asList("t", "mergetextures"), "Use the same texture for all models"); 22 | parser.acceptsAll(asList("r", "scalemc"), "Resize model to mc standard (shrink by factor of 16)"); 23 | } 24 | 25 | protected void main(OptionParser parser, OptionSet options) { 26 | int flags = 0; 27 | if(options.has("o2")) flags |= QBImporter.TEXTUREPLANES; 28 | if(options.has("s")) flags |= QBImporter.SQUARETEXTURE; 29 | if(options.has("t")) flags |= QBImporter.MERGETEXTURES; 30 | if(options.has("r")) flags |= QBImporter.SCALEMC; 31 | 32 | File[] input = options.valuesOf("input").toArray(new File[0]); 33 | File[] outDir = new File[input.length]; 34 | if(options.has("out")) { 35 | File output = (File)options.valueOf("out"); 36 | if(output.isFile()) 37 | throw new RuntimeException("Output Path is not a directory"); 38 | if(!output.exists()) 39 | output.mkdirs(); 40 | 41 | for(int i = 0; i < input.length; i++) 42 | outDir[i] = output; 43 | } else { 44 | for(int i = 0; i < input.length; i++) 45 | outDir[i] = input[i].isDirectory() ? input[i] : input[i].getParentFile(); 46 | } 47 | 48 | for(int i = 0; i < input.length; i++) { 49 | File file = input[i]; 50 | if(file.isDirectory()) { 51 | for(File file2 : file.listFiles()) 52 | if(file2.getName().endsWith(".qb")) 53 | convert(file2, outDir[i], flags); 54 | } 55 | else 56 | convert(file, outDir[i], flags); 57 | } 58 | } 59 | 60 | private void convert(File in, File outDir, int flags) { 61 | System.out.println("Converting: "+in.getName()); 62 | QBImporter.RasterisedModel m = QBImporter.loadQB(in).toRasterisedModel(flags); 63 | m.export(new File(outDir, in.getName().replace(".qb", ".obj")), outDir); 64 | } 65 | 66 | @Override 67 | public String name() { 68 | return "QBConverter"; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/codechicken/lib/util/Copyable.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.util; 2 | 3 | public interface Copyable { 4 | public T copy(); 5 | } 6 | -------------------------------------------------------------------------------- /src/codechicken/lib/util/LangProxy.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.util; 2 | 3 | import net.minecraft.util.StatCollector; 4 | 5 | public class LangProxy 6 | { 7 | public final String namespace; 8 | 9 | public LangProxy(String namespace) { 10 | this.namespace = namespace+"."; 11 | } 12 | 13 | public String translate(String key) { 14 | return StatCollector.translateToLocal(namespace+key); 15 | } 16 | 17 | public String format(String key, Object... params) { 18 | return StatCollector.translateToLocalFormatted(namespace+key, params); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/AxisCycle.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | public class AxisCycle 4 | { 5 | public static Transformation[] cycles = new Transformation[]{ 6 | new RedundantTransformation(), 7 | new VariableTransformation(new Matrix4(0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1)){ 8 | @Override public void apply(Vector3 vec){ 9 | double d0 = vec.x; double d1 = vec.y; double d2 = vec.z; 10 | vec.x = d2; vec.y = d0; vec.z = d1; 11 | } @Override public Transformation inverse(){ 12 | return cycles[2]; 13 | }}, 14 | new VariableTransformation(new Matrix4(0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1)){ 15 | @Override public void apply(Vector3 vec){ 16 | double d0 = vec.x; double d1 = vec.y; double d2 = vec.z; 17 | vec.x = d1; vec.y = d2; vec.z = d0; 18 | } @Override public Transformation inverse(){ 19 | return cycles[1]; 20 | }}}; 21 | } 22 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/Cuboid6.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | import codechicken.lib.util.Copyable; 4 | import net.minecraft.block.Block; 5 | import net.minecraft.util.AxisAlignedBB; 6 | 7 | import java.math.BigDecimal; 8 | import java.math.MathContext; 9 | import java.math.RoundingMode; 10 | 11 | public class Cuboid6 implements Copyable 12 | { 13 | public static Cuboid6 full = new Cuboid6(0, 0, 0, 1, 1, 1); 14 | 15 | public Vector3 min; 16 | public Vector3 max; 17 | 18 | public Cuboid6() { 19 | this(new Vector3(), new Vector3()); 20 | } 21 | 22 | public Cuboid6(Vector3 min, Vector3 max) { 23 | this.min = min; 24 | this.max = max; 25 | } 26 | 27 | public Cuboid6(AxisAlignedBB aabb) { 28 | min = new Vector3(aabb.minX, aabb.minY, aabb.minZ); 29 | max = new Vector3(aabb.maxX, aabb.maxY, aabb.maxZ); 30 | } 31 | 32 | public Cuboid6(Cuboid6 cuboid) { 33 | min = cuboid.min.copy(); 34 | max = cuboid.max.copy(); 35 | } 36 | 37 | public Cuboid6(double minx, double miny, double minz, double maxx, double maxy, double maxz) { 38 | min = new Vector3(minx, miny, minz); 39 | max = new Vector3(maxx, maxy, maxz); 40 | } 41 | 42 | public AxisAlignedBB aabb() { 43 | return AxisAlignedBB.fromBounds(min.x, min.y, min.z, max.x, max.y, max.z); 44 | } 45 | 46 | public Cuboid6 copy() { 47 | return new Cuboid6(this); 48 | } 49 | 50 | public Cuboid6 set(Cuboid6 c) { 51 | return set(c.min, c.max); 52 | } 53 | 54 | public Cuboid6 set(Vector3 min, Vector3 max) { 55 | this.min.set(min); 56 | this.max.set(max); 57 | return this; 58 | } 59 | 60 | public Cuboid6 set(double minx, double miny, double minz, double maxx, double maxy, double maxz) { 61 | min.set(minx, miny, minz); 62 | max.set(maxx, maxy, maxz); 63 | return this; 64 | } 65 | 66 | public Cuboid6 add(Vector3 vec) { 67 | min.add(vec); 68 | max.add(vec); 69 | return this; 70 | } 71 | 72 | public Cuboid6 sub(Vector3 vec) { 73 | min.subtract(vec); 74 | max.subtract(vec); 75 | return this; 76 | } 77 | 78 | public Cuboid6 expand(double d) { 79 | return expand(new Vector3(d, d, d)); 80 | } 81 | 82 | public Cuboid6 expand(Vector3 vec) { 83 | min.sub(vec); 84 | max.add(vec); 85 | return this; 86 | } 87 | 88 | public void setBlockBounds(Block block) { 89 | block.setBlockBounds((float) min.x, (float) min.y, (float) min.z, (float) max.x, (float) max.y, (float) max.z); 90 | } 91 | 92 | public boolean intersects(Cuboid6 b) { 93 | return max.x - 1E-5 > b.min.x && 94 | b.max.x - 1E-5 > min.x && 95 | max.y - 1E-5 > b.min.y && 96 | b.max.y - 1E-5 > min.y && 97 | max.z - 1E-5 > b.min.z && 98 | b.max.z - 1E-5 > min.z; 99 | } 100 | 101 | public Cuboid6 offset(Cuboid6 o) { 102 | min.add(o.min); 103 | max.add(o.max); 104 | return this; 105 | } 106 | 107 | public Vector3 center() { 108 | return min.copy().add(max).multiply(0.5); 109 | } 110 | 111 | public static boolean intersects(Cuboid6 a, Cuboid6 b) { 112 | return a != null && b != null && a.intersects(b); 113 | } 114 | 115 | public String toString() { 116 | MathContext cont = new MathContext(4, RoundingMode.HALF_UP); 117 | return "Cuboid: (" + new BigDecimal(min.x, cont) + ", " + new BigDecimal(min.y, cont) + ", " + new BigDecimal(min.z, cont) + ") -> (" + 118 | new BigDecimal(max.x, cont) + ", " + new BigDecimal(max.y, cont) + ", " + new BigDecimal(max.z, cont) + ")"; 119 | } 120 | 121 | public Cuboid6 enclose(Vector3 vec) { 122 | if (min.x > vec.x) min.x = vec.x; 123 | if (min.y > vec.y) min.y = vec.y; 124 | if (min.z > vec.z) min.z = vec.z; 125 | if (max.x < vec.x) max.x = vec.x; 126 | if (max.y < vec.y) max.y = vec.y; 127 | if (max.z < vec.z) max.z = vec.z; 128 | return this; 129 | } 130 | 131 | public Cuboid6 enclose(Cuboid6 c) { 132 | if (min.x > c.min.x) min.x = c.min.x; 133 | if (min.y > c.min.y) min.y = c.min.y; 134 | if (min.z > c.min.z) min.z = c.min.z; 135 | if (max.x < c.max.x) max.x = c.max.x; 136 | if (max.y < c.max.y) max.y = c.max.y; 137 | if (max.z < c.max.z) max.z = c.max.z; 138 | return this; 139 | } 140 | 141 | public Cuboid6 apply(Transformation t) { 142 | t.apply(min); 143 | t.apply(max); 144 | double temp; 145 | if(min.x > max.x) {temp = min.x; min.x = max.x; max.x = temp;} 146 | if(min.y > max.y) {temp = min.y; min.y = max.y; max.y = temp;} 147 | if(min.z > max.z) {temp = min.z; min.z = max.z; max.z = temp;} 148 | return this; 149 | } 150 | 151 | public double getSide(int s) { 152 | switch(s) { 153 | case 0: return min.y; 154 | case 1: return max.y; 155 | case 2: return min.z; 156 | case 3: return max.z; 157 | case 4: return min.x; 158 | case 5: return max.x; 159 | } 160 | throw new IndexOutOfBoundsException("Switch Falloff"); 161 | } 162 | 163 | public Cuboid6 setSide(int s, double d) { 164 | switch(s) { 165 | case 0: min.y = d; break; 166 | case 1: max.y = d; break; 167 | case 2: min.z = d; break; 168 | case 3: max.z = d; break; 169 | case 4: min.x = d; break; 170 | case 5: max.x = d; break; 171 | default: throw new IndexOutOfBoundsException("Switch Falloff"); 172 | } 173 | return this; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/CuboidCoord.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | import codechicken.lib.util.Copyable; 4 | import net.minecraft.util.AxisAlignedBB; 5 | 6 | import java.util.Iterator; 7 | 8 | public class CuboidCoord implements Iterable, Copyable 9 | { 10 | public BlockCoord min; 11 | public BlockCoord max; 12 | 13 | public CuboidCoord() 14 | { 15 | min = new BlockCoord(); 16 | max = new BlockCoord(); 17 | } 18 | 19 | public CuboidCoord(BlockCoord min, BlockCoord max) 20 | { 21 | this.min = min; 22 | this.max = max; 23 | } 24 | 25 | public CuboidCoord(BlockCoord coord) 26 | { 27 | this(coord, coord.copy()); 28 | } 29 | 30 | public CuboidCoord(int[] ia) 31 | { 32 | this(ia[0], ia[1], ia[2], ia[3], ia[4], ia[5]); 33 | } 34 | 35 | public CuboidCoord(int x1, int y1, int z1, int x2, int y2, int z2) 36 | { 37 | this(new BlockCoord(x1, y1, z1), new BlockCoord(x2, y2, z2)); 38 | } 39 | 40 | public CuboidCoord expand(int amount) { 41 | return expand(amount, amount, amount); 42 | } 43 | 44 | public CuboidCoord expand(int x, int y, int z) { 45 | max.add(x, y, z); 46 | min.sub(x, y, z); 47 | return this; 48 | } 49 | 50 | public CuboidCoord expand(int side, int amount) 51 | { 52 | if(side%2 == 0)//negative side 53 | min = min.offset(side, amount); 54 | else 55 | max = max.offset(side, amount); 56 | return this; 57 | } 58 | 59 | public int size(int s) 60 | { 61 | switch(s) 62 | { 63 | case 0: 64 | case 1: 65 | return max.y - min.y+1; 66 | case 2: 67 | case 3: 68 | return max.z - min.z+1; 69 | case 4: 70 | case 5: 71 | return max.x - min.x+1; 72 | default: 73 | return 0; 74 | } 75 | } 76 | 77 | public int getSide(int s) 78 | { 79 | switch(s) 80 | { 81 | case 0: return min.y; 82 | case 1: return max.y; 83 | case 2: return min.z; 84 | case 3: return max.z; 85 | case 4: return min.x; 86 | case 5: return max.x; 87 | } 88 | throw new IndexOutOfBoundsException("Switch Falloff"); 89 | } 90 | 91 | public CuboidCoord setSide(int s, int v) 92 | { 93 | switch(s) 94 | { 95 | case 0: min.y = v; break; 96 | case 1: max.y = v; break; 97 | case 2: min.z = v; break; 98 | case 3: max.z = v; break; 99 | case 4: min.x = v; break; 100 | case 5: max.x = v; break; 101 | default: throw new IndexOutOfBoundsException("Switch Falloff"); 102 | } 103 | return this; 104 | } 105 | 106 | public int getVolume() 107 | { 108 | return (max.x-min.x+1)*(max.y-min.y+1)*(max.z-min.z+1); 109 | } 110 | 111 | public Vector3 getCenterVec() 112 | { 113 | return new Vector3(min.x+(max.x-min.x+1)/2D, min.y+(max.y-min.y+1)/2D, min.z+(max.z-min.z+1)/2D); 114 | } 115 | 116 | public BlockCoord getCenter(BlockCoord store) 117 | { 118 | store.set(min.x+(max.x-min.x)/2, min.y+(max.y-min.y)/2, min.z+(max.z-min.z)/2); 119 | return store; 120 | } 121 | 122 | public boolean contains(BlockCoord coord) 123 | { 124 | return contains(coord.x, coord.y, coord.z); 125 | } 126 | 127 | public boolean contains(int x, int y, int z) 128 | { 129 | return x >= min.x && x <= max.x 130 | && y >= min.y && y <= max.y 131 | && z >= min.z && z <= max.z; 132 | } 133 | 134 | public int[] intArray() 135 | { 136 | return new int[]{min.x, min.y, min.z, max.x, max.y, max.z}; 137 | } 138 | 139 | public CuboidCoord copy() 140 | { 141 | return new CuboidCoord(min.copy(), max.copy()); 142 | } 143 | 144 | public Cuboid6 bounds() 145 | { 146 | return new Cuboid6(min.x, min.y, min.z, max.x+1, max.y+1, max.z+1); 147 | } 148 | 149 | public AxisAlignedBB toAABB() 150 | { 151 | return bounds().aabb(); 152 | } 153 | 154 | public void set(BlockCoord min, BlockCoord max) 155 | { 156 | this.min.set(min); 157 | this.max.set(max); 158 | } 159 | 160 | public CuboidCoord set(int x1, int y1, int z1, int x2, int y2, int z2) 161 | { 162 | min.set(x1, y1, z1); 163 | max.set(x2, y2, z2); 164 | return this; 165 | } 166 | 167 | public CuboidCoord set(BlockCoord coord) { 168 | min.set(coord); 169 | max.set(coord); 170 | return this; 171 | } 172 | 173 | public CuboidCoord set(int[] ia) 174 | { 175 | return set(ia[0], ia[1], ia[2], ia[3], ia[4], ia[5]); 176 | } 177 | 178 | public CuboidCoord include(BlockCoord coord) { 179 | return include(coord.x, coord.y, coord.z); 180 | } 181 | 182 | public CuboidCoord include(int x, int y, int z) { 183 | if(x < min.x) min.x = x; 184 | else if(x > max.x) max.x = x; 185 | if(y < min.y) min.y = y; 186 | else if(y > max.y) max.y = y; 187 | if(z < min.z) min.z = z; 188 | else if(z > max.z) max.z = z; 189 | return this; 190 | } 191 | 192 | public Iterator iterator() { 193 | return new Iterator() { 194 | BlockCoord b = null; 195 | 196 | public boolean hasNext() { 197 | return b == null || !b.equals(max); 198 | } 199 | 200 | public BlockCoord next() { 201 | if(b == null) 202 | b = min.copy(); 203 | else { 204 | if(b.z != max.z) 205 | b.z++; 206 | else { 207 | b.z = min.z; 208 | if(b.y != max.y) 209 | b.y++; 210 | else { 211 | b.y = min.y; 212 | b.x++; 213 | } 214 | } 215 | } 216 | return b.copy(); 217 | } 218 | 219 | public void remove() { 220 | throw new UnsupportedOperationException(); 221 | } 222 | }; 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/ITransformation.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | /** 4 | * Abstract supertype for any VectorN transformation 5 | * @param The vector type 6 | * @param The transformation type 7 | */ 8 | public abstract class ITransformation 9 | { 10 | /** 11 | * Applies this transformation to vec 12 | */ 13 | public abstract void apply(Vector vec); 14 | 15 | /** 16 | * @param point The point to apply this transformation around 17 | * @return Wraps this transformation in a translation to point and then back from point 18 | */ 19 | public abstract Transformation at(Vector point); 20 | 21 | /** 22 | * Creates a TransformationList composed of this transformation followed by t 23 | * If this is a TransformationList, the transformation will be appended and this returned 24 | */ 25 | public abstract Transformation with(Transformation t); 26 | 27 | /** 28 | * Returns a simplified transformation that performs this, followed by next. If such a transformation does not exist, returns null 29 | */ 30 | public Transformation merge(Transformation next) { 31 | return null; 32 | } 33 | 34 | /** 35 | * Returns true if this transformation is redundant, eg. Scale(1, 1, 1), Translation(0, 0, 0) or Rotation(0, a, b, c) 36 | */ 37 | public boolean isRedundant() { 38 | return false; 39 | } 40 | 41 | public abstract Transformation inverse(); 42 | 43 | /** 44 | * Scala ++ operator 45 | */ 46 | public Transformation $plus$plus(Transformation t) { 47 | return with(t); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/IrreversibleTransformationException.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | @SuppressWarnings("serial") 4 | public class IrreversibleTransformationException extends RuntimeException 5 | { 6 | public ITransformation t; 7 | 8 | public IrreversibleTransformationException(ITransformation t) 9 | { 10 | this.t = t; 11 | } 12 | 13 | @Override 14 | public String getMessage() 15 | { 16 | return "The following transformation is irreversible:\n"+t; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/Line3.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | 4 | public class Line3 5 | { 6 | public static final double tol = 0.0001D; 7 | 8 | public Vector3 pt1; 9 | public Vector3 pt2; 10 | 11 | public Line3(Vector3 pt1, Vector3 pt2) 12 | { 13 | this.pt1 = pt1; 14 | this.pt2 = pt2; 15 | } 16 | 17 | public Line3() 18 | { 19 | this(new Vector3(), new Vector3()); 20 | } 21 | 22 | public static boolean intersection2D(Line3 line1, Line3 line2, Vector3 store) 23 | { 24 | // calculate differences 25 | double xD1 = line1.pt2.x - line1.pt1.x; 26 | double zD1 = line1.pt2.z - line1.pt1.z; 27 | double xD2 = line2.pt2.x - line2.pt1.x; 28 | double zD2 = line2.pt2.z - line2.pt1.z; 29 | 30 | double xD3 = line1.pt1.x - line2.pt1.x; 31 | double zD3 = line1.pt1.z - line2.pt1.z; 32 | 33 | double div = zD2 * xD1 - xD2 * zD1; 34 | if(div == 0)//lines are parallel 35 | return false; 36 | double ua = (xD2 * zD3 - zD2 * xD3) / div; 37 | store.set(line1.pt1.x + ua * xD1, 0, line1.pt1.z + ua * zD1); 38 | 39 | if(store.x >= Math.min(line1.pt1.x, line1.pt2.x)-tol && store.x >= Math.min(line2.pt1.x, line2.pt2.x)-tol 40 | && store.z >= Math.min(line1.pt1.z, line1.pt2.z)-tol && store.z >= Math.min(line2.pt1.z, line2.pt2.z)-tol 41 | && store.x <= Math.max(line1.pt1.x, line1.pt2.x)+tol && store.x <= Math.max(line2.pt1.x, line2.pt2.x)+tol 42 | && store.z <= Math.max(line1.pt1.z, line1.pt2.z)+tol && store.z <= Math.max(line2.pt1.z, line2.pt2.z)+tol) 43 | return true; 44 | 45 | return false; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/Quat.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | import codechicken.lib.math.MathHelper; 4 | import codechicken.lib.util.Copyable; 5 | 6 | import java.math.BigDecimal; 7 | import java.math.MathContext; 8 | import java.math.RoundingMode; 9 | 10 | public class Quat implements Copyable 11 | { 12 | public double x; 13 | public double y; 14 | public double z; 15 | public double s; 16 | 17 | public Quat() 18 | { 19 | s = 1; 20 | x = 0; 21 | y = 0; 22 | z = 0; 23 | } 24 | 25 | public Quat(Quat quat) 26 | { 27 | x = quat.x; 28 | y = quat.y; 29 | z = quat.z; 30 | s = quat.s; 31 | } 32 | 33 | public Quat(double d, double d1, double d2, double d3) 34 | { 35 | x = d1; 36 | y = d2; 37 | z = d3; 38 | s = d; 39 | } 40 | 41 | public Quat set(Quat quat) 42 | { 43 | x = quat.x; 44 | y = quat.y; 45 | z = quat.z; 46 | s = quat.s; 47 | 48 | return this; 49 | } 50 | 51 | public Quat set(double d, double d1, double d2, double d3) 52 | { 53 | x = d1; 54 | y = d2; 55 | z = d3; 56 | s = d; 57 | 58 | return this; 59 | } 60 | 61 | public static Quat aroundAxis(double ax, double ay, double az, double angle) 62 | { 63 | return new Quat().setAroundAxis(ax, ay, az, angle); 64 | } 65 | 66 | public static Quat aroundAxis(Vector3 axis, double angle) 67 | { 68 | return aroundAxis(axis.x, axis.y, axis.z, angle); 69 | } 70 | 71 | public Quat setAroundAxis(double ax, double ay, double az, double angle) 72 | { 73 | angle *= 0.5; 74 | double d4 = MathHelper.sin(angle); 75 | return set(MathHelper.cos(angle), ax * d4, ay * d4, az * d4); 76 | } 77 | 78 | public Quat setAroundAxis(Vector3 axis, double angle) 79 | { 80 | return setAroundAxis(axis.x, axis.y, axis.z, angle); 81 | } 82 | 83 | public Quat multiply(Quat quat) 84 | { 85 | double d = s * quat.s - x * quat.x - y * quat.y - z * quat.z; 86 | double d1 = s * quat.x + x * quat.s - y * quat.z + z * quat.y; 87 | double d2 = s * quat.y + x * quat.z + y * quat.s - z * quat.x; 88 | double d3 = s * quat.z - x * quat.y + y * quat.x + z * quat.s; 89 | s = d; 90 | x = d1; 91 | y = d2; 92 | z = d3; 93 | 94 | return this; 95 | } 96 | 97 | public Quat rightMultiply(Quat quat) 98 | { 99 | double d = s * quat.s - x * quat.x - y * quat.y - z * quat.z; 100 | double d1 = s * quat.x + x * quat.s + y * quat.z - z * quat.y; 101 | double d2 = s * quat.y - x * quat.z + y * quat.s + z * quat.x; 102 | double d3 = s * quat.z + x * quat.y - y * quat.x + z * quat.s; 103 | s = d; 104 | x = d1; 105 | y = d2; 106 | z = d3; 107 | 108 | return this; 109 | } 110 | 111 | public double mag() 112 | { 113 | return Math.sqrt(x * x + y * y + z * z + s * s); 114 | } 115 | 116 | public Quat normalize() 117 | { 118 | double d = mag(); 119 | if(d != 0) 120 | { 121 | d = 1 / d; 122 | x *= d; 123 | y *= d; 124 | z *= d; 125 | s *= d; 126 | } 127 | 128 | return this; 129 | } 130 | 131 | public Quat copy() 132 | { 133 | return new Quat(this); 134 | } 135 | 136 | public void rotate(Vector3 vec) 137 | { 138 | double d = -x * vec.x - y * vec.y - z * vec.z; 139 | double d1 = s * vec.x + y * vec.z - z * vec.y; 140 | double d2 = s * vec.y - x * vec.z + z * vec.x; 141 | double d3 = s * vec.z + x * vec.y - y * vec.x; 142 | vec.x = d1 * s - d * x - d2 * z + d3 * y; 143 | vec.y = d2 * s - d * y + d1 * z - d3 * x; 144 | vec.z = d3 * s - d * z - d1 * y + d2 * x; 145 | } 146 | 147 | public String toString() 148 | { 149 | MathContext cont = new MathContext(4, RoundingMode.HALF_UP); 150 | return "Quat("+new BigDecimal(s, cont)+", "+new BigDecimal(x, cont)+", "+new BigDecimal(y, cont)+", "+new BigDecimal(z, cont)+")"; 151 | } 152 | 153 | public Rotation rotation() 154 | { 155 | return new Rotation(this); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/Rectangle4i.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | public class Rectangle4i 4 | { 5 | public int x; 6 | public int y; 7 | public int w; 8 | public int h; 9 | 10 | public Rectangle4i() { 11 | } 12 | 13 | public Rectangle4i(int x, int y, int w, int h) { 14 | this.x = x; 15 | this.y = y; 16 | this.w = w; 17 | this.h = h; 18 | } 19 | 20 | public int x1() { 21 | return x; 22 | } 23 | 24 | public int y1() { 25 | return y; 26 | } 27 | 28 | public int x2() { 29 | return x + w - 1; 30 | } 31 | 32 | public int y2() { 33 | return y + h - 1; 34 | } 35 | 36 | public void set(int x, int y, int w, int h) { 37 | this.x = x; 38 | this.y = y; 39 | this.w = w; 40 | this.h = h; 41 | } 42 | 43 | public Rectangle4i offset(int dx, int dy) { 44 | x += dx; 45 | y += dy; 46 | return this; 47 | } 48 | 49 | public Rectangle4i include(int px, int py) { 50 | if (px < x) expand(px - x, 0); 51 | if (px >= x + w) expand(px - x - w + 1, 0); 52 | if (py < y) expand(0, py - y); 53 | if (py >= y + h) expand(0, py - y - h + 1); 54 | return this; 55 | } 56 | 57 | public Rectangle4i include(Rectangle4i r) { 58 | include(r.x, r.y); 59 | return include(r.x2(), r.y2()); 60 | } 61 | 62 | public Rectangle4i expand(int px, int py) { 63 | if (px > 0) 64 | w += px; 65 | else { 66 | x += px; 67 | w -= px; 68 | } 69 | if (py > 0) 70 | h += py; 71 | else { 72 | y += py; 73 | h -= py; 74 | } 75 | return this; 76 | } 77 | 78 | public boolean contains(int px, int py) { 79 | return x <= px && px < x + w && y <= py && py < y + h; 80 | } 81 | 82 | public boolean intersects(Rectangle4i r) { 83 | return r.x + r.w > x && 84 | r.x < x + w && 85 | r.y + r.h > y && 86 | r.y < y + h; 87 | } 88 | 89 | public int area() { 90 | return w * h; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/RedundantTransformation.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | import net.minecraftforge.fml.relauncher.Side; 4 | import net.minecraftforge.fml.relauncher.SideOnly; 5 | 6 | public class RedundantTransformation extends Transformation 7 | { 8 | @Override 9 | public void apply(Vector3 vec){} 10 | 11 | @Override 12 | public void apply(Matrix4 mat){} 13 | 14 | @Override 15 | public void applyN(Vector3 normal){} 16 | 17 | @Override 18 | public Transformation at(Vector3 point) 19 | { 20 | return this; 21 | } 22 | 23 | @Override 24 | @SideOnly(Side.CLIENT) 25 | public void glApply(){} 26 | 27 | @Override 28 | public Transformation inverse() 29 | { 30 | return this; 31 | } 32 | 33 | @Override 34 | public Transformation merge(Transformation next) { 35 | return next; 36 | } 37 | 38 | @Override 39 | public boolean isRedundant() { 40 | return true; 41 | } 42 | 43 | @Override 44 | public String toString() 45 | { 46 | return "Nothing()"; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/Scale.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | import net.minecraft.client.renderer.GlStateManager; 4 | import net.minecraftforge.fml.relauncher.Side; 5 | import net.minecraftforge.fml.relauncher.SideOnly; 6 | 7 | import java.math.BigDecimal; 8 | import java.math.MathContext; 9 | import java.math.RoundingMode; 10 | 11 | public class Scale extends Transformation { 12 | public Vector3 factor; 13 | 14 | public Scale(Vector3 factor) { 15 | this.factor = factor; 16 | } 17 | 18 | public Scale(double factor) { 19 | this(new Vector3(factor, factor, factor)); 20 | } 21 | 22 | public Scale(double x, double y, double z) { 23 | this(new Vector3(x, y, z)); 24 | } 25 | 26 | @Override 27 | public void apply(Vector3 vec) { 28 | vec.multiply(factor); 29 | } 30 | 31 | @Override 32 | public void applyN(Vector3 normal) { 33 | } 34 | 35 | @Override 36 | public void apply(Matrix4 mat) { 37 | mat.scale(factor); 38 | } 39 | 40 | @Override 41 | @SideOnly(Side.CLIENT) 42 | public void glApply() { 43 | GlStateManager.scale(factor.x, factor.y, factor.z); 44 | } 45 | 46 | @Override 47 | public Transformation inverse() { 48 | return new Scale(1 / factor.x, 1 / factor.y, 1 / factor.z); 49 | } 50 | 51 | @Override 52 | public Transformation merge(Transformation next) { 53 | if (next instanceof Scale) 54 | return new Scale(factor.copy().multiply(((Scale) next).factor)); 55 | 56 | return null; 57 | } 58 | 59 | @Override 60 | public boolean isRedundant() { 61 | return factor.equalsT(Vector3.one); 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | MathContext cont = new MathContext(4, RoundingMode.HALF_UP); 67 | return "Scale(" + new BigDecimal(factor.x, cont) + ", " + new BigDecimal(factor.y, cont) + ", " + new BigDecimal(factor.z, cont) + ")"; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/SwapYZ.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | public class SwapYZ extends VariableTransformation 4 | { 5 | public SwapYZ() 6 | { 7 | super(new Matrix4( 8 | 1, 0, 0, 0, 9 | 0, 0, 1, 0, 10 | 0, 1, 0, 0, 11 | 0, 0, 0, 1)); 12 | } 13 | 14 | @Override 15 | public void apply(Vector3 vec) 16 | { 17 | double vz = vec.z; 18 | vec.z = vec.y; 19 | vec.y = vz; 20 | } 21 | 22 | @Override 23 | public Transformation inverse() 24 | { 25 | return this; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/Transformation.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | import codechicken.lib.render.CCRenderState; 4 | import net.minecraftforge.fml.relauncher.Side; 5 | import net.minecraftforge.fml.relauncher.SideOnly; 6 | 7 | /** 8 | * Abstract supertype for any 3D vector transformation 9 | */ 10 | public abstract class Transformation extends ITransformation implements CCRenderState.IVertexOperation 11 | { 12 | public static final int operationIndex = CCRenderState.registerOperation(); 13 | 14 | /** 15 | * Applies this transformation to a normal (doesn't translate) 16 | * @param normal The normal to transform 17 | */ 18 | public abstract void applyN(Vector3 normal); 19 | 20 | /** 21 | * Applies this transformation to a matrix as a multiplication on the right hand side. 22 | * @param mat The matrix to combine this transformation with 23 | */ 24 | public abstract void apply(Matrix4 mat); 25 | 26 | public Transformation at(Vector3 point) { 27 | return new TransformationList(new Translation(-point.x, -point.y, -point.z), this, point.translation()); 28 | } 29 | 30 | public TransformationList with(Transformation t) { 31 | return new TransformationList(this, t); 32 | } 33 | 34 | @SideOnly(Side.CLIENT) 35 | public abstract void glApply(); 36 | 37 | @Override 38 | public boolean load() { 39 | CCRenderState.pipeline.addRequirement(CCRenderState.normalAttrib.operationID()); 40 | return !isRedundant(); 41 | } 42 | 43 | @Override 44 | public void operate() { 45 | apply(CCRenderState.vert.vec); 46 | if(CCRenderState.normalAttrib.active) 47 | applyN(CCRenderState.normal); 48 | } 49 | 50 | @Override 51 | public int operationID() { 52 | return operationIndex; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/TransformationList.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | import net.minecraftforge.fml.relauncher.Side; 4 | import net.minecraftforge.fml.relauncher.SideOnly; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Iterator; 8 | 9 | public class TransformationList extends Transformation 10 | { 11 | private ArrayList transformations = new ArrayList(); 12 | private Matrix4 mat; 13 | 14 | public TransformationList(Transformation... transforms) 15 | { 16 | for(Transformation t : transforms) 17 | if(t instanceof TransformationList) 18 | transformations.addAll(((TransformationList)t).transformations); 19 | else 20 | transformations.add(t); 21 | 22 | compact(); 23 | } 24 | 25 | public Matrix4 compile() 26 | { 27 | if(mat == null) 28 | { 29 | mat = new Matrix4(); 30 | for(int i = transformations.size()-1; i >= 0; i--) 31 | transformations.get(i).apply(mat); 32 | } 33 | return mat; 34 | } 35 | 36 | /** 37 | * Returns a global space matrix as opposed to an object space matrix (reverse application order) 38 | * @return 39 | */ 40 | public Matrix4 reverseCompile() 41 | { 42 | Matrix4 mat = new Matrix4(); 43 | for(Transformation t : transformations) 44 | t.apply(mat); 45 | return mat; 46 | } 47 | 48 | @Override 49 | public void apply(Vector3 vec) 50 | { 51 | if(mat != null) 52 | mat.apply(vec); 53 | else 54 | for(int i = 0; i < transformations.size(); i++) 55 | transformations.get(i).apply(vec); 56 | } 57 | 58 | @Override 59 | public void applyN(Vector3 normal) 60 | { 61 | if(mat != null) 62 | mat.applyN(normal); 63 | else 64 | for(int i = 0; i < transformations.size(); i++) 65 | transformations.get(i).applyN(normal); 66 | } 67 | 68 | @Override 69 | public void apply(Matrix4 mat) 70 | { 71 | mat.multiply(compile()); 72 | } 73 | 74 | @Override 75 | public TransformationList with(Transformation t) 76 | { 77 | if(t.isRedundant()) 78 | return this; 79 | 80 | mat = null;//matrix invalid 81 | if(t instanceof TransformationList) 82 | transformations.addAll(((TransformationList)t).transformations); 83 | else 84 | transformations.add(t); 85 | 86 | compact(); 87 | return this; 88 | } 89 | 90 | public TransformationList prepend(Transformation t) 91 | { 92 | if(t.isRedundant()) 93 | return this; 94 | 95 | mat = null;//matrix invalid 96 | if(t instanceof TransformationList) 97 | transformations.addAll(0, ((TransformationList)t).transformations); 98 | else 99 | transformations.add(0, t); 100 | 101 | compact(); 102 | return this; 103 | } 104 | 105 | private void compact() { 106 | ArrayList newList = new ArrayList(transformations.size()); 107 | Iterator iterator = transformations.iterator(); 108 | Transformation prev = null; 109 | while(iterator.hasNext()) { 110 | Transformation t = iterator.next(); 111 | if(t.isRedundant()) 112 | continue; 113 | 114 | if(prev != null) { 115 | Transformation m = prev.merge(t); 116 | if(m == null) 117 | newList.add(prev); 118 | else if(m.isRedundant()) 119 | t = null; 120 | else 121 | t = m; 122 | } 123 | prev = t; 124 | } 125 | if(prev != null) 126 | newList.add(prev); 127 | 128 | if(newList.size() < transformations.size()) { 129 | transformations = newList; 130 | mat = null; 131 | } 132 | 133 | if(transformations.size() > 3 && mat == null) 134 | compile(); 135 | } 136 | 137 | @Override 138 | public boolean isRedundant() { 139 | return transformations.size() == 0; 140 | } 141 | 142 | @Override 143 | @SideOnly(Side.CLIENT) 144 | public void glApply() 145 | { 146 | for(int i = transformations.size()-1; i >= 0; i--) 147 | transformations.get(i).glApply(); 148 | } 149 | 150 | @Override 151 | public Transformation inverse() 152 | { 153 | TransformationList rev = new TransformationList(); 154 | for(int i = transformations.size()-1; i >= 0; i--) 155 | rev.with(transformations.get(i).inverse()); 156 | return rev; 157 | } 158 | 159 | @Override 160 | public String toString() 161 | { 162 | String s = ""; 163 | for(Transformation t : transformations) 164 | s+="\n"+t.toString(); 165 | return s.trim(); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/Translation.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | import net.minecraft.client.renderer.GlStateManager; 4 | import net.minecraftforge.fml.relauncher.Side; 5 | import net.minecraftforge.fml.relauncher.SideOnly; 6 | 7 | import java.math.BigDecimal; 8 | import java.math.MathContext; 9 | import java.math.RoundingMode; 10 | 11 | public class Translation extends Transformation { 12 | public Vector3 vec; 13 | 14 | public Translation(Vector3 vec) { 15 | this.vec = vec; 16 | } 17 | 18 | public Translation(double x, double y, double z) { 19 | this(new Vector3(x, y, z)); 20 | } 21 | 22 | @Override 23 | public void apply(Vector3 vec) { 24 | vec.add(this.vec); 25 | } 26 | 27 | @Override 28 | public void applyN(Vector3 normal) { 29 | } 30 | 31 | @Override 32 | public void apply(Matrix4 mat) { 33 | mat.translate(vec); 34 | } 35 | 36 | @Override 37 | public Transformation at(Vector3 point) { 38 | return this; 39 | } 40 | 41 | @Override 42 | @SideOnly(Side.CLIENT) 43 | public void glApply() { 44 | GlStateManager.translate(vec.x, vec.y, vec.z); 45 | } 46 | 47 | @Override 48 | public Transformation inverse() { 49 | return new Translation(-vec.x, -vec.y, -vec.z); 50 | } 51 | 52 | @Override 53 | public Transformation merge(Transformation next) { 54 | if (next instanceof Translation) 55 | return new Translation(vec.copy().add(((Translation) next).vec)); 56 | 57 | return null; 58 | } 59 | 60 | @Override 61 | public boolean isRedundant() { 62 | return vec.equalsT(Vector3.zero); 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | MathContext cont = new MathContext(4, RoundingMode.HALF_UP); 68 | return "Translation(" + new BigDecimal(vec.x, cont) + ", " + new BigDecimal(vec.y, cont) + ", " + new BigDecimal(vec.z, cont) + ")"; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/codechicken/lib/vec/VariableTransformation.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.vec; 2 | 3 | import net.minecraftforge.fml.relauncher.Side; 4 | import net.minecraftforge.fml.relauncher.SideOnly; 5 | 6 | public abstract class VariableTransformation extends Transformation 7 | { 8 | public Matrix4 mat; 9 | 10 | public VariableTransformation(Matrix4 mat) 11 | { 12 | this.mat = mat; 13 | } 14 | 15 | @Override 16 | public void applyN(Vector3 normal) 17 | { 18 | apply(normal); 19 | } 20 | 21 | @Override 22 | public void apply(Matrix4 mat) 23 | { 24 | mat.multiply(this.mat); 25 | } 26 | 27 | @Override 28 | @SideOnly(Side.CLIENT) 29 | public void glApply() 30 | { 31 | mat.glApply(); 32 | } 33 | } -------------------------------------------------------------------------------- /src/codechicken/lib/world/ChunkExtension.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.world; 2 | 3 | import net.minecraft.entity.player.EntityPlayerMP; 4 | import net.minecraft.nbt.NBTTagCompound; 5 | import net.minecraft.network.Packet; 6 | import net.minecraft.world.ChunkCoordIntPair; 7 | import net.minecraft.world.chunk.Chunk; 8 | 9 | import java.util.HashSet; 10 | 11 | public abstract class ChunkExtension 12 | { 13 | public final Chunk chunk; 14 | public final ChunkCoordIntPair coord; 15 | public final WorldExtension world; 16 | public HashSet watchedPlayers; 17 | 18 | public ChunkExtension(Chunk chunk, WorldExtension world) 19 | { 20 | this.chunk = chunk; 21 | coord = chunk.getChunkCoordIntPair(); 22 | this.world = world; 23 | watchedPlayers = new HashSet(); 24 | } 25 | 26 | public void loadData(NBTTagCompound tag) 27 | { 28 | } 29 | 30 | public void saveData(NBTTagCompound tag) 31 | { 32 | } 33 | 34 | public void load() 35 | { 36 | } 37 | 38 | public void unload() 39 | { 40 | } 41 | 42 | public final void sendPacketToPlayers(Packet packet) 43 | { 44 | for(EntityPlayerMP player : watchedPlayers) 45 | player.playerNetServerHandler.sendPacket(packet); 46 | } 47 | 48 | public final void watchPlayer(EntityPlayerMP player) 49 | { 50 | watchedPlayers.add(player); 51 | onWatchPlayer(player); 52 | } 53 | 54 | public void onWatchPlayer(EntityPlayerMP player) 55 | { 56 | } 57 | 58 | public final void unwatchPlayer(EntityPlayerMP player) 59 | { 60 | watchedPlayers.remove(player); 61 | onUnWatchPlayer(player); 62 | } 63 | 64 | public void onUnWatchPlayer(EntityPlayerMP player) 65 | { 66 | } 67 | 68 | public void sendUpdatePackets() 69 | { 70 | } 71 | 72 | @Override 73 | public int hashCode() 74 | { 75 | return coord.chunkXPos ^ coord.chunkZPos; 76 | } 77 | 78 | @Override 79 | public boolean equals(Object o) 80 | { 81 | return (o instanceof ChunkExtension && ((ChunkExtension)o).coord.equals(coord)) || 82 | (o instanceof ChunkCoordIntPair && coord.equals(o)) || 83 | (o instanceof Long && (Long)o == (((long)coord.chunkXPos)<<32 | coord.chunkZPos)); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/codechicken/lib/world/IChunkLoadTile.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.world; 2 | 3 | /** 4 | * Provides a callback for tile entities when a chunk is loaded, as an alternative to validate when the chunk hasn't been added to the world. 5 | * To hook all world join/seperate events. Use this, TileEntity.validate with a worldObj.blockExists check, TileEntity.onChunkUnload and TileEntity.invalidate 6 | * Be sure to call TileChunkLoadHook.init() from your mod during initialisation 7 | * You could easily implement this in your own mod, but providing it here reduces the number of times the chunkTileEntityMap needs to be iterated 8 | */ 9 | public interface IChunkLoadTile 10 | { 11 | public void onChunkLoad(); 12 | } 13 | -------------------------------------------------------------------------------- /src/codechicken/lib/world/TileChunkLoadHook.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.world; 2 | 3 | import net.minecraft.tileentity.TileEntity; 4 | import net.minecraftforge.common.MinecraftForge; 5 | import net.minecraftforge.event.world.ChunkEvent; 6 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class TileChunkLoadHook 15 | { 16 | private static boolean init; 17 | public static void init() { 18 | if(init) return; 19 | init = true; 20 | 21 | MinecraftForge.EVENT_BUS.register(new TileChunkLoadHook()); 22 | } 23 | 24 | @SubscribeEvent 25 | public void onChunkLoad(ChunkEvent.Load event) { 26 | List list = new ArrayList(event.getChunk().chunkTileEntityMap.values()); 27 | for(TileEntity t : list) 28 | if(t instanceof IChunkLoadTile) 29 | ((IChunkLoadTile)t).onChunkLoad(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/codechicken/lib/world/WorldExtension.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.world; 2 | 3 | import net.minecraft.entity.player.EntityPlayerMP; 4 | import net.minecraft.nbt.NBTTagCompound; 5 | import net.minecraft.util.BlockPos; 6 | import net.minecraft.world.World; 7 | import net.minecraft.world.chunk.Chunk; 8 | 9 | import java.util.HashMap; 10 | 11 | public abstract class WorldExtension 12 | { 13 | public final World world; 14 | public HashMap chunkMap = new HashMap(); 15 | 16 | public WorldExtension(World world) 17 | { 18 | this.world = world; 19 | } 20 | 21 | public void load() 22 | { 23 | } 24 | 25 | public void unload() 26 | { 27 | } 28 | 29 | public void save() 30 | { 31 | } 32 | 33 | public void preTick() 34 | { 35 | } 36 | 37 | public void postTick() 38 | { 39 | } 40 | 41 | protected final void addChunk(ChunkExtension extension) 42 | { 43 | chunkMap.put(extension.chunk, extension); 44 | } 45 | 46 | protected final void loadChunk(Chunk chunk) 47 | { 48 | chunkMap.get(chunk).load(); 49 | } 50 | 51 | protected final void unloadChunk(Chunk chunk) 52 | { 53 | chunkMap.get(chunk).unload(); 54 | } 55 | 56 | protected final void loadChunkData(Chunk chunk, NBTTagCompound tag) 57 | { 58 | chunkMap.get(chunk).loadData(tag); 59 | } 60 | 61 | protected final void saveChunkData(Chunk chunk, NBTTagCompound tag) 62 | { 63 | chunkMap.get(chunk).saveData(tag); 64 | } 65 | 66 | protected final void remChunk(Chunk chunk) 67 | { 68 | chunkMap.remove(chunk); 69 | } 70 | 71 | protected final void watchChunk(Chunk chunk, EntityPlayerMP player) 72 | { 73 | chunkMap.get(chunk).watchPlayer(player); 74 | } 75 | 76 | protected final void unwatchChunk(Chunk chunk, EntityPlayerMP player) 77 | { 78 | ChunkExtension extension = chunkMap.get(chunk); 79 | if(extension != null) 80 | extension.unwatchPlayer(player); 81 | } 82 | 83 | protected final void sendChunkUpdates(Chunk chunk) 84 | { 85 | chunkMap.get(chunk).sendUpdatePackets(); 86 | } 87 | 88 | public boolean containsChunk(Chunk chunk) 89 | { 90 | return chunkMap.containsKey(chunk); 91 | } 92 | 93 | public ChunkExtension getChunkExtension(int chunkXPos, int chunkZPos) 94 | { 95 | if(!world.isBlockLoaded(new BlockPos(chunkXPos<<4, 128, chunkZPos<<4))) 96 | return null; 97 | 98 | return chunkMap.get(world.getChunkFromChunkCoords(chunkXPos, chunkZPos)); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/codechicken/lib/world/WorldExtensionInstantiator.java: -------------------------------------------------------------------------------- 1 | package codechicken.lib.world; 2 | 3 | import net.minecraft.world.World; 4 | import net.minecraft.world.chunk.Chunk; 5 | 6 | public abstract class WorldExtensionInstantiator 7 | { 8 | public int instantiatorID; 9 | 10 | public abstract WorldExtension createWorldExtension(World world); 11 | public abstract ChunkExtension createChunkExtension(Chunk chunk, WorldExtension world); 12 | 13 | public WorldExtension getExtension(World world) 14 | { 15 | return WorldExtensionManager.getWorldExtension(world, instantiatorID); 16 | } 17 | } 18 | --------------------------------------------------------------------------------