commit 3d5821df5f92c1319b4da1f5e68d325ad9f580e8 Author: MrTJP Date: Sun Jan 25 16:50:47 2015 -0500 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cb2f338 --- /dev/null +++ b/.gitignore @@ -0,0 +1,66 @@ +#ant stuff +/bin/ +#Remove OS generated garbage +*/.DS_Store +.DS_Store +.DS_Store? +.Spotlight-V100 +.Trashes +Icon? +ehthumbs.db +Thumbs.db +#gradle stuff +/.gradle +/build/ +/run/ +#IDEA files from Gradle +.idea/ +/*.iml +/*.ipr +/*.iws +#Vim backups +*~ +#eclipse stuffs +/.classpath +/.project +/.settings/ +/debug/ +*.lock +/.metadata/ +/config/ +/logs/ +options.txt +/saves/ +#sbt-eclipse junk +/target/ +#Modeling stuff +*.blend1 +*.blend2 +#libs +/libs/ +/assets/ +/out/ +/crash-reports/ +/asm/ +/mods/ +*.log +#Server stuff +banned-ips.txt +banned-players.txt +ops.txt +server.properties +servers.dat +white-list.txt +/world/ +banned-ips.json +banned-ips.txt.converted +banned-players.json +banned-players.txt.converted +eula.txt +ops.txt.converted +ops.json +usercache.json +white-list.txt.converted +whitelist.json +world-20140811-075700.zip +.cache diff --git a/build.gradle b/build.gradle new file mode 100755 index 0000000..fd7cffd --- /dev/null +++ b/build.gradle @@ -0,0 +1,247 @@ +import org.apache.tools.ant.filters.ReplaceTokens +import groovy.xml.MarkupBuilder + +import java.text.SimpleDateFormat + +buildscript { + repositories { + mavenCentral() + maven { + name = "forge" + url = "http://files.minecraftforge.net/maven" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/repositories/snapshots/" + } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT' + } +} + +repositories { + maven { + name "chickenbones" + url "http://chickenbones.net/maven/" + } + + maven { + name "mvnmrtjp" + url "http://projectredwiki.com/maven" + } +} + +apply plugin: 'scala' +apply plugin: 'forge' + +group = "mrtjp" +archivesBaseName = "ForgeRelocation" + +ext.configFile = file "build.properties" +configFile.withReader { + def prop = new Properties() + prop.load(it) + //Referred to as 'config' or 'project.config' + project.ext.config = new ConfigSlurper().parse prop +} + +configurations { + deployerJars +} + +dependencies { + deployerJars "org.apache.maven.wagon:wagon-ftp:2.2" + compile "codechicken:CodeChickenLib:${config.mc.version}-${config.ccl.version}:dev" + compile "mrtjp:MrTJPCore:${config.mc.version}-${config.mrtjp.version}:dev" +} + +def build_number = project.hasProperty("manualbuildnum") ? project.manualbuildnum : (System.getenv("BUILD_NUMBER") ?: "1") +version = "${project.config.mod.version}."+build_number +println config.mc.version+"-"+config.forge.version + +minecraft { + version = config.mc.version+"-"+config.forge.version + if (file('../run').exists()) { + runDir = "../run" + } else { + runDir = "run" + } +} + +sourceSets { + main { + def root = project.projectDir + scala { + srcDir new File(root, "src") + } + resources { + srcDir new File(root, "resources") + } + } +} + +task updateVersion(type: Copy) { + // Replace tokens + from(sourceSets.main.scala.srcDirs) + into 'build/sources/scala' + filter(ReplaceTokens, tokens: [ + 'VERSION' : config.mod.version, + 'BUILD_NUMBER' : build_number, + 'MC_VERSION' : config.mc.version, + 'FORGE_VERSION': config.forge.version, + 'CCL_VERSION' : config.ccl.version, + 'MRTJP_VERSION': config.mrtjp.version + ]) +} + +processResources { + //redo task if any of these properties change + inputs.property "version", project.version + inputs.property "mc.version", config.mc.version + inputs.property "ccl.version", config.ccl.version + + // Replace properties in all files + from(sourceSets.main.resources.srcDirs) { + include '**.info' + filter(ReplaceTokens, tokens: [ + 'VERSION' : config.mod.version, + 'BUILD_NUMBER' : build_number, + 'MC_VERSION' : config.mc.version, + 'FORGE_VERSION': config.forge.version, + 'CCL_VERSION' : config.ccl.version, + 'MRTJP_VERSION': config.mrtjp.version + ]) + } + // Copy everything else + from(sourceSets.main.resources.srcDirs) { + include 'assets/**/*.*' + } +} + + +task deobfJar(type: Jar) { + from sourceSets.main.output + classifier = 'dev' +} + +task sourceJar(type: Jar) { + from sourceSets.main.allSource + classifier = 'sources' +} + +task apiJar(type: Jar) { + from(sourceSets.main.allSource) { + include "**/relocation/api/**" + } + classifier = 'api' +} + +jar { + manifest { + attributes 'FMLCorePlugin': 'mrtjp.relocation.asm.RelocationPlugin' + attributes 'FMLCorePluginContainsFMLMod': 'true' + } + classifier = 'universal' +} + +def deployMetaFile() +{ + new File(new File(project.projectDir, "build/libs/"), + "deploymeta-${project.minecraft.version}-${project.version}.xml") +} + +def createDeployMeta() +{ + def writer = new StringWriter() + def xml = new MarkupBuilder(writer) + + def today = new SimpleDateFormat('dd-MM-yyyy').format(new Date()) + + xml.deployMeta() { + modversion(version) + + date(today) + + deps { + Minecraft(project.minecraft.version) + Forge(config.forge.version) + MrTJPCore(config.mrtjp.version) + CCL(config.ccl.version) + } + + isPublic(true) + + isRecommended(false) + } + + def file = deployMetaFile() + + def stream = new FileOutputStream(file) + stream.write(writer.toString().getBytes()) + stream.flush() + stream.close() +} + +artifacts { + archives deobfJar + archives sourceJar + archives apiJar + archives deployMetaFile() +} + +uploadArchives { + dependsOn 'reobf' + doFirst {createDeployMeta()} + repositories { + if (project.hasProperty("mavenurl")) + { + mavenDeployer { + configuration = configurations.deployerJars + + repository(url: project.mavenurl) { + authentication(userName: project.mavenusername, password: project.mavenpassword) + } + + pom { + groupId = project.group + version = "${project.minecraft.version}-${project.version}" + artifactId = project.archivesBaseName + project { + name project.archivesBaseName + packaging 'jar' + description project.archivesBaseName + url 'https://github.com/MrTJP/'+project.archivesBaseName + + scm { + url 'https://github.com/MrTJP/'+project.archivesBaseName + connection 'scm:git:git://github.com/MrTJP/'+project.archivesBaseName+'.git' + developerConnection 'scm:git:git@github.com:MrTJP/'+project.archivesBaseName+'.git' + } + + issueManagement { + system 'github' + url 'https://github.com/MrTJP/'+project.archivesBaseName+'/issues' + } + + licenses { + license { + name 'Restricted Public Software License (RPSL) v1.3.1' + url 'https://raw.githubusercontent.com/MrTJP/ProjectRed/master/LICENSE.md' + distribution 'repo' + } + } + + developers { + developer { + id 'mrtjp' + name 'mrtjp' + roles { role 'developer' } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/build.properties b/build.properties new file mode 100644 index 0000000..3f755b4 --- /dev/null +++ b/build.properties @@ -0,0 +1,7 @@ +mod.version=0.0.1a + +mc.version=1.7.10 +forge.version=10.13.2.1277 + +mrtjp.version=1.0.5.11 +ccl.version=1.1.1.110 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100755 index 0000000..b761216 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 0000000..678d9d8 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Jul 02 15:54:47 CDT 2014 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-bin.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..91a7e26 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/resources/Changelog b/resources/Changelog new file mode 100644 index 0000000..600427f --- /dev/null +++ b/resources/Changelog @@ -0,0 +1,2 @@ +v0.0.1a +- Initial alpha release \ No newline at end of file diff --git a/resources/assets/relocation/lang/en_US.lang b/resources/assets/relocation/lang/en_US.lang new file mode 100755 index 0000000..00fa9d4 --- /dev/null +++ b/resources/assets/relocation/lang/en_US.lang @@ -0,0 +1,2 @@ +tile.relocation.blockframe=Frame +tile.relocation.blockmotor=Frame Motor \ No newline at end of file diff --git a/resources/assets/relocation/textures/blocks/frame.png b/resources/assets/relocation/textures/blocks/frame.png new file mode 100644 index 0000000..daec978 Binary files /dev/null and b/resources/assets/relocation/textures/blocks/frame.png differ diff --git a/resources/assets/relocation/textures/blocks/frame.psd b/resources/assets/relocation/textures/blocks/frame.psd new file mode 100644 index 0000000..98bf6c7 Binary files /dev/null and b/resources/assets/relocation/textures/blocks/frame.psd differ diff --git a/resources/assets/relocation/textures/blocks/motor/bottom.png b/resources/assets/relocation/textures/blocks/motor/bottom.png new file mode 100644 index 0000000..3e9db28 Binary files /dev/null and b/resources/assets/relocation/textures/blocks/motor/bottom.png differ diff --git a/resources/assets/relocation/textures/blocks/motor/side.png b/resources/assets/relocation/textures/blocks/motor/side.png new file mode 100644 index 0000000..8ba03d6 Binary files /dev/null and b/resources/assets/relocation/textures/blocks/motor/side.png differ diff --git a/resources/assets/relocation/textures/blocks/motor/sidee.png b/resources/assets/relocation/textures/blocks/motor/sidee.png new file mode 100644 index 0000000..ba88a7e Binary files /dev/null and b/resources/assets/relocation/textures/blocks/motor/sidee.png differ diff --git a/resources/assets/relocation/textures/blocks/motor/sidew.png b/resources/assets/relocation/textures/blocks/motor/sidew.png new file mode 100644 index 0000000..f29408c Binary files /dev/null and b/resources/assets/relocation/textures/blocks/motor/sidew.png differ diff --git a/resources/assets/relocation/textures/blocks/motor/top.png b/resources/assets/relocation/textures/blocks/motor/top.png new file mode 100644 index 0000000..be5b895 Binary files /dev/null and b/resources/assets/relocation/textures/blocks/motor/top.png differ diff --git a/resources/assets/relocation/textures/obj/frame.blend b/resources/assets/relocation/textures/obj/frame.blend new file mode 100644 index 0000000..9f8096e Binary files /dev/null and b/resources/assets/relocation/textures/obj/frame.blend differ diff --git a/resources/assets/relocation/textures/obj/frame.obj b/resources/assets/relocation/textures/obj/frame.obj new file mode 100644 index 0000000..6c1385a --- /dev/null +++ b/resources/assets/relocation/textures/obj/frame.obj @@ -0,0 +1,267 @@ +# Blender v2.71 (sub 5) OBJ File: 'frame.blend' +# www.blender.org +g support_Cube.010 +v 0.375030 0.380070 0.468458 +v 0.437530 0.380070 0.468458 +v 0.437530 0.468458 0.380070 +v 0.375030 0.468458 0.380070 +v 0.375030 -0.468458 -0.380070 +v 0.437530 -0.468458 -0.380070 +v 0.437530 -0.380070 -0.468458 +v 0.375030 -0.380070 -0.468458 +v 0.375020 0.468458 -0.380070 +v 0.437520 0.468458 -0.380070 +v 0.437520 0.380070 -0.468458 +v 0.375020 0.380070 -0.468458 +v 0.375020 -0.380070 0.468458 +v 0.437520 -0.380070 0.468458 +v 0.437520 -0.468458 0.380070 +v 0.375020 -0.468458 0.380070 +v -0.380070 -0.437510 0.468458 +v -0.380070 -0.375010 0.468458 +v -0.468458 -0.375010 0.380070 +v -0.468458 -0.437510 0.380070 +v 0.468458 -0.437510 -0.380070 +v 0.468458 -0.375010 -0.380070 +v 0.380070 -0.375010 -0.468458 +v 0.380070 -0.437510 -0.468458 +v -0.468458 -0.437520 -0.380070 +v -0.468458 -0.375020 -0.380070 +v -0.380070 -0.375020 -0.468458 +v -0.380070 -0.437520 -0.468458 +v 0.380070 -0.437520 0.468458 +v 0.380070 -0.375020 0.468458 +v 0.468458 -0.375020 0.380070 +v 0.468458 -0.437520 0.380070 +v -0.380070 0.375030 0.468458 +v -0.380070 0.437530 0.468458 +v -0.468458 0.437530 0.380070 +v -0.468458 0.375030 0.380070 +v 0.468458 0.375030 -0.380070 +v 0.468458 0.437530 -0.380070 +v 0.380070 0.437530 -0.468458 +v 0.380070 0.375030 -0.468458 +v -0.468458 0.375020 -0.380070 +v -0.468458 0.437520 -0.380070 +v -0.380070 0.437520 -0.468458 +v -0.380070 0.375020 -0.468458 +v 0.380070 0.375020 0.468458 +v 0.380070 0.437520 0.468458 +v 0.468458 0.437520 0.380070 +v 0.468458 0.375020 0.380070 +v -0.380070 0.468458 0.437510 +v -0.380070 0.468458 0.375010 +v -0.468458 0.380070 0.375010 +v -0.468458 0.380070 0.437510 +v 0.468458 -0.380070 0.437510 +v 0.468458 -0.380070 0.375010 +v 0.380070 -0.468458 0.375010 +v 0.380070 -0.468458 0.437510 +v -0.468458 -0.380070 0.437520 +v -0.468458 -0.380070 0.375020 +v -0.380070 -0.468458 0.375020 +v -0.380070 -0.468458 0.437520 +v 0.380070 0.468458 0.437520 +v 0.380070 0.468458 0.375020 +v 0.468458 0.380070 0.375020 +v 0.468458 0.380070 0.437520 +v -0.380070 0.468458 -0.375030 +v -0.380070 0.468458 -0.437530 +v -0.468458 0.380070 -0.437530 +v -0.468458 0.380070 -0.375030 +v 0.468458 -0.380070 -0.375030 +v 0.468458 -0.380070 -0.437530 +v 0.380070 -0.468458 -0.437530 +v 0.380070 -0.468458 -0.375030 +v -0.468458 -0.380070 -0.375020 +v -0.468458 -0.380070 -0.437520 +v -0.380070 -0.468458 -0.437520 +v -0.380070 -0.468458 -0.375020 +v 0.380070 0.468458 -0.375020 +v 0.380070 0.468458 -0.437520 +v 0.468458 0.380070 -0.437520 +v 0.468458 0.380070 -0.375020 +v -0.437510 0.380070 0.468458 +v -0.375010 0.380070 0.468458 +v -0.375010 0.468458 0.380070 +v -0.437510 0.468458 0.380070 +v -0.437510 -0.468458 -0.380070 +v -0.375010 -0.468458 -0.380070 +v -0.375010 -0.380070 -0.468458 +v -0.437510 -0.380070 -0.468458 +v -0.437520 0.468458 -0.380070 +v -0.375020 0.468458 -0.380070 +v -0.375020 0.380070 -0.468458 +v -0.437520 0.380070 -0.468458 +v -0.437520 -0.380070 0.468458 +v -0.375020 -0.380070 0.468458 +v -0.375020 -0.468458 0.380070 +v -0.437520 -0.468458 0.380070 +vt 0.312500 0.000000 +vt 0.375000 0.000000 +vt 0.375000 1.000000 +vt 0.312500 1.000000 +vt 0.500000 0.000000 +vt 0.500000 1.000000 +vt 0.562500 0.000000 +vt 0.562500 1.000000 +vt 0.687500 1.000000 +vt 0.687500 0.000000 +s 1 +f 5/1 6/2 2/3 1/4 +f 6/2 7/5 3/6 2/3 +f 7/5 8/7 4/8 3/6 +f 8/9 5/8 1/7 4/10 +f 13/1 14/2 10/3 9/4 +f 14/2 15/5 11/6 10/3 +f 15/5 16/7 12/8 11/6 +f 16/9 13/8 9/7 12/10 +f 21/1 22/2 18/3 17/4 +f 22/2 23/5 19/6 18/3 +f 23/5 24/7 20/8 19/6 +f 24/9 21/8 17/7 20/10 +f 29/1 30/2 26/3 25/4 +f 30/2 31/5 27/6 26/3 +f 31/5 32/7 28/8 27/6 +f 32/9 29/8 25/7 28/10 +f 37/1 38/2 34/3 33/4 +f 38/2 39/5 35/6 34/3 +f 39/5 40/7 36/8 35/6 +f 40/9 37/8 33/7 36/10 +f 45/1 46/2 42/3 41/4 +f 46/2 47/5 43/6 42/3 +f 47/5 48/7 44/8 43/6 +f 48/9 45/8 41/7 44/10 +f 53/1 54/2 50/3 49/4 +f 54/2 55/5 51/6 50/3 +f 55/5 56/7 52/8 51/6 +f 56/9 53/8 49/7 52/10 +f 61/1 62/2 58/3 57/4 +f 62/2 63/5 59/6 58/3 +f 63/5 64/7 60/8 59/6 +f 64/9 61/8 57/7 60/10 +f 69/1 70/2 66/3 65/4 +f 70/2 71/5 67/6 66/3 +f 71/5 72/7 68/8 67/6 +f 72/9 69/8 65/7 68/10 +f 77/1 78/2 74/3 73/4 +f 78/2 79/5 75/6 74/3 +f 79/5 80/7 76/8 75/6 +f 80/9 77/8 73/7 76/10 +f 85/1 86/2 82/3 81/4 +f 86/2 87/5 83/6 82/3 +f 87/5 88/7 84/8 83/6 +f 88/9 85/8 81/7 84/10 +f 93/1 94/2 90/3 89/4 +f 94/2 95/5 91/6 90/3 +f 95/5 96/7 92/8 91/6 +f 96/9 93/8 89/7 92/10 +g frame_Cube.001 +v -0.500000 0.500000 0.500000 +v -0.500000 0.500000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 -0.375000 -0.375000 +v -0.500000 0.375000 -0.375000 +v -0.500000 0.375000 0.375000 +v -0.500000 -0.375000 0.375000 +v -0.500000 -0.500000 0.500000 +v -0.375000 0.375000 0.500000 +v 0.375000 0.375000 0.500000 +v 0.500000 0.500000 0.500000 +v -0.375000 -0.375000 0.500000 +v -0.375000 0.500000 0.375000 +v -0.375000 0.500000 -0.375000 +v 0.375000 0.500000 -0.375000 +v 0.500000 0.500000 -0.500000 +v -0.375000 0.375000 -0.500000 +v -0.375000 -0.375000 -0.500000 +v 0.375000 0.375000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v 0.375000 -0.500000 -0.375000 +v -0.375000 -0.500000 -0.375000 +v -0.375000 -0.500000 0.375000 +v -0.375000 -0.375000 0.375000 +v -0.375000 0.375000 0.375000 +v 0.375000 0.375000 0.375000 +v 0.500000 -0.500000 0.500000 +v 0.375000 -0.375000 0.500000 +v 0.375000 0.500000 0.375000 +v -0.375000 0.375000 0.000000 +v -0.375000 0.375000 -0.375000 +v 0.375000 -0.375000 -0.500000 +v 0.375000 -0.500000 0.375000 +v 0.375000 -0.375000 -0.375000 +v -0.375000 -0.375000 -0.375000 +v -0.375000 -0.375000 0.000000 +v 0.375000 -0.375000 0.375000 +v 0.500000 -0.375000 -0.375000 +v 0.500000 -0.375000 0.375000 +v 0.500000 0.375000 0.375000 +v 0.500000 0.375000 -0.375000 +v 0.375000 0.375000 -0.000000 +v 0.375000 0.375000 -0.375000 +v 0.375000 -0.375000 -0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.875000 0.875000 +vt 0.875000 0.125000 +vt 0.000000 1.000000 +vt 0.125000 0.875000 +vt 0.125000 0.125000 +vt 0.000000 0.000000 +vt 0.250000 0.875000 +vt 0.250000 0.125000 +vt 0.750000 0.875000 +vt 0.750000 0.125000 +vt 0.750000 0.500000 +vt 0.250000 0.500000 +vt 0.125000 0.500000 +s 1 +f 98/11 99/12 100/13 101/14 +f 104/15 103/16 100/13 99/12 +f 108/13 105/14 97/11 104/12 +f 98/12 110/13 111/14 112/11 +f 113/17 114/16 99/15 98/18 +f 99/11 116/12 117/13 118/14 +f 106/17 105/16 121/19 122/20 +f 124/16 123/15 107/18 106/17 +f 97/15 107/18 125/17 109/16 +f 128/13 115/14 112/11 116/12 +f 123/15 129/16 117/13 116/12 +f 123/12 116/15 134/16 135/13 +f 112/18 137/17 134/16 116/15 +f 130/21 117/13 129/14 133/22 140/23 +f 126/23 127/21 110/13 109/14 121/22 +f 127/22 139/21 111/13 110/14 +f 127/21 113/13 115/14 139/22 +f 131/21 114/13 113/14 127/22 +f 118/17 117/16 130/19 131/20 +f 108/17 124/16 133/19 120/20 +f 133/21 124/13 106/14 122/22 +f 122/17 121/16 109/19 125/20 +f 115/17 128/16 130/19 139/20 +f 130/16 128/19 114/20 131/17 +f 129/17 119/16 120/19 133/20 +f 137/17 136/16 122/19 138/24 139/20 +f 134/17 137/16 139/19 130/20 +f 136/17 135/16 133/19 122/20 +f 130/22 140/23 133/21 135/13 134/14 +f 127/17 126/25 121/16 102/19 101/20 +f 131/22 127/21 101/13 100/14 +f 121/22 120/21 103/13 102/14 +f 100/17 103/16 120/19 132/24 131/20 +f 105/17 108/16 120/19 121/20 +f 119/17 118/16 131/19 132/24 120/20 +f 125/17 111/16 139/19 138/24 122/20 +f 107/11 136/14 137/17 112/18 +f 107/11 123/12 135/13 136/14 +f 108/13 104/12 123/15 124/16 +f 105/14 106/17 107/18 97/11 +f 97/18 102/17 103/16 104/15 +f 97/18 98/11 101/14 102/17 +f 115/14 113/17 98/18 112/11 +f 114/16 128/13 116/12 99/15 +f 107/18 112/11 111/14 125/17 +f 97/15 109/16 110/13 98/12 +f 104/18 99/11 118/14 119/17 +f 104/18 119/17 129/16 123/15 diff --git a/resources/assets/relocation/textures/obj/frame_simple.blend b/resources/assets/relocation/textures/obj/frame_simple.blend new file mode 100644 index 0000000..2ee9fb0 Binary files /dev/null and b/resources/assets/relocation/textures/obj/frame_simple.blend differ diff --git a/resources/assets/relocation/textures/obj/frame_simple.obj b/resources/assets/relocation/textures/obj/frame_simple.obj new file mode 100644 index 0000000..79742af --- /dev/null +++ b/resources/assets/relocation/textures/obj/frame_simple.obj @@ -0,0 +1,237 @@ +# Blender v2.71 (sub 5) OBJ File: 'frame_simple.blend' +# www.blender.org +g frame_frame_Cube.001 +v -0.500000 0.500000 -0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 -0.375000 -0.375000 +v -0.500000 0.375000 -0.375000 +v -0.500000 -0.500000 0.500000 +v -0.500000 -0.375000 0.375000 +v -0.375000 -0.375000 0.500000 +v -0.375000 0.375000 0.500000 +v -0.500000 0.500000 0.500000 +v -0.375000 0.500000 -0.375000 +v 0.375000 0.500000 -0.375000 +v 0.500000 0.500000 -0.500000 +v -0.375000 0.375000 -0.500000 +v -0.375000 -0.375000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v 0.375000 -0.500000 -0.375000 +v -0.375000 -0.500000 -0.375000 +v 0.375000 0.375000 0.500000 +v -0.375000 0.375000 0.375000 +v 0.375000 0.375000 0.375000 +v 0.375000 -0.375000 0.500000 +v 0.500000 -0.500000 0.500000 +v 0.500000 0.500000 0.500000 +v 0.375000 0.500000 0.375000 +v -0.375000 0.500000 0.375000 +v 0.375000 -0.375000 -0.500000 +v 0.375000 0.375000 -0.500000 +v 0.375000 -0.500000 0.375000 +v 0.500000 -0.375000 -0.375000 +v 0.500000 -0.375000 0.375000 +v 0.500000 0.375000 -0.375000 +v 0.375000 -0.375000 -0.375000 +v 0.375000 -0.375000 0.375000 +v 0.375000 -0.375000 -0.000000 +v -0.375000 0.375000 0.000000 +v -0.375000 0.375000 -0.375000 +v 0.375000 0.375000 -0.375000 +v -0.375000 -0.375000 -0.375000 +v -0.375000 -0.375000 0.375000 +v -0.375000 -0.500000 0.375000 +v 0.500000 0.375000 0.375000 +v 0.375000 0.375000 0.000000 +v -0.500000 0.375000 0.375000 +v -0.375000 -0.375000 -0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.875000 0.875000 +vt 0.875000 0.125000 +vt 0.000000 1.000000 +vt 0.125000 0.875000 +vt 0.000000 0.000000 +vt 0.125000 0.125000 +vt 0.250000 0.875000 +vt 0.250000 0.125000 +vt 0.750000 0.125000 +vt 0.750000 0.875000 +vt 0.125000 0.500000 +vt 0.750000 0.500000 +vt 0.250000 0.500000 +s 1 +f 1/1 2/2 3/3 4/4 +f 5/5 6/6 3/3 2/2 +f 7/3 8/4 9/1 5/2 +f 1/2 10/3 11/4 12/1 +f 2/5 1/7 13/8 14/6 +f 2/1 15/2 16/3 17/4 +f 18/8 8/6 19/9 20/10 +f 21/6 22/5 23/7 18/8 +f 9/5 23/7 24/8 25/6 +f 26/3 27/4 12/1 15/2 +f 22/5 28/6 16/3 15/2 +f 22/2 15/5 29/6 30/3 +f 12/7 31/8 29/6 15/5 +f 36/11 37/12 11/3 10/4 +f 36/12 13/3 27/4 37/11 +f 38/12 14/3 13/4 36/11 +f 17/8 16/6 32/9 38/10 +f 7/8 21/6 33/9 39/10 +f 33/12 21/3 18/4 20/11 +f 20/8 19/6 25/9 24/10 +f 27/8 26/6 32/9 37/10 +f 32/6 26/9 14/10 38/8 +f 28/8 40/6 39/9 33/10 +f 29/8 31/6 37/9 32/10 +f 41/8 30/6 33/9 20/10 +f 38/11 36/12 4/3 3/4 +f 19/11 39/12 6/3 43/4 +f 8/8 7/6 39/9 19/10 +f 23/1 41/4 31/8 12/7 +f 23/1 22/2 30/3 41/4 +f 7/3 5/2 22/5 21/6 +f 8/4 18/8 23/7 9/1 +f 9/7 43/8 6/6 5/5 +f 9/7 1/1 4/4 43/8 +f 1/7 12/1 27/4 13/8 +f 14/6 26/3 15/2 2/5 +f 23/7 12/1 11/4 24/8 +f 10/3 1/2 9/5 25/6 +f 5/7 2/1 17/4 40/8 +f 5/7 40/8 28/6 22/5 +f 43/9 4/10 36/8 35/13 19/6 +f 33/11 34/14 32/12 16/3 28/4 +f 44/15 38/10 3/8 6/6 39/9 +f 35/14 36/12 10/3 25/4 19/11 +f 42/15 37/10 31/8 41/6 20/9 +f 34/14 33/12 30/3 29/4 32/11 +f 40/8 17/6 38/9 44/15 39/10 +f 42/15 20/10 24/8 11/6 37/9 +g support_Cube.004 +v -0.437495 0.380070 0.468458 +v -0.437495 0.468458 0.380070 +v -0.437495 -0.468458 -0.380070 +v -0.437495 -0.380070 -0.468458 +v -0.437505 0.468458 -0.380070 +v -0.437505 0.380070 -0.468458 +v -0.437505 -0.380070 0.468458 +v -0.437505 -0.468458 0.380070 +v -0.437495 0.380070 0.468458 +v -0.437495 0.468458 0.380070 +v -0.437495 -0.468458 -0.380070 +v -0.437495 -0.380070 -0.468458 +v -0.437505 0.468458 -0.380070 +v -0.437505 0.380070 -0.468458 +v -0.437505 -0.380070 0.468458 +v -0.437505 -0.468458 0.380070 +v 0.437505 0.380070 0.468458 +v 0.437505 0.468458 0.380070 +v 0.437505 -0.468458 -0.380070 +v 0.437505 -0.380070 -0.468458 +v 0.437495 0.468458 -0.380070 +v 0.437495 0.380070 -0.468458 +v 0.437495 -0.380070 0.468458 +v 0.437495 -0.468458 0.380070 +v 0.437505 0.380070 0.468458 +v 0.437505 0.468458 0.380070 +v 0.437505 -0.468458 -0.380070 +v 0.437505 -0.380070 -0.468458 +v 0.437495 0.468458 -0.380070 +v 0.437495 0.380070 -0.468458 +v 0.437495 -0.380070 0.468458 +v 0.437495 -0.468458 0.380070 +v -0.380070 -0.437495 0.468458 +v -0.468458 -0.437495 0.380070 +v 0.468458 -0.437495 -0.380070 +v 0.380070 -0.437495 -0.468458 +v -0.468458 -0.437505 -0.380070 +v -0.380070 -0.437505 -0.468458 +v 0.380070 -0.437505 0.468458 +v 0.468458 -0.437505 0.380070 +v -0.380070 -0.437495 0.468458 +v -0.468458 -0.437495 0.380070 +v 0.468458 -0.437495 -0.380070 +v 0.380070 -0.437495 -0.468458 +v -0.468458 -0.437505 -0.380070 +v -0.380070 -0.437505 -0.468458 +v 0.380070 -0.437505 0.468458 +v 0.468458 -0.437505 0.380070 +v -0.380070 0.437505 0.468458 +v -0.468458 0.437505 0.380070 +v 0.468458 0.437505 -0.380070 +v 0.380070 0.437505 -0.468458 +v -0.468458 0.437495 -0.380070 +v -0.380070 0.437495 -0.468458 +v 0.380070 0.437495 0.468458 +v 0.468458 0.437495 0.380070 +v -0.380070 0.437505 0.468458 +v -0.468458 0.437505 0.380070 +v 0.468458 0.437505 -0.380070 +v 0.380070 0.437505 -0.468458 +v -0.468458 0.437495 -0.380070 +v -0.380070 0.437495 -0.468458 +v 0.380070 0.437495 0.468458 +v 0.468458 0.437495 0.380070 +v -0.380070 0.468458 0.437495 +v -0.468458 0.380070 0.437495 +v 0.468458 -0.380070 0.437495 +v 0.380070 -0.468458 0.437495 +v -0.468458 -0.380070 0.437505 +v -0.380070 -0.468458 0.437505 +v 0.380070 0.468458 0.437505 +v 0.468458 0.380070 0.437505 +v -0.380070 0.468458 0.437495 +v -0.468458 0.380070 0.437495 +v 0.468458 -0.380070 0.437495 +v 0.380070 -0.468458 0.437495 +v -0.468458 -0.380070 0.437505 +v -0.380070 -0.468458 0.437505 +v 0.380070 0.468458 0.437505 +v 0.468458 0.380070 0.437505 +v -0.380070 0.468458 -0.437505 +v -0.468458 0.380070 -0.437505 +v 0.468458 -0.380070 -0.437505 +v 0.380070 -0.468458 -0.437505 +v -0.468458 -0.380070 -0.437495 +v -0.380070 -0.468458 -0.437495 +v 0.380070 0.468458 -0.437495 +v 0.468458 0.380070 -0.437495 +v -0.380070 0.468458 -0.437505 +v -0.468458 0.380070 -0.437505 +v 0.468458 -0.380070 -0.437505 +v 0.380070 -0.468458 -0.437505 +v -0.468458 -0.380070 -0.437495 +v -0.380070 -0.468458 -0.437495 +v 0.380070 0.468458 -0.437495 +v 0.468458 0.380070 -0.437495 +vt 0.687500 1.000000 +vt 0.562500 1.000000 +vt 0.562500 0.000000 +vt 0.687500 0.000000 +s off +f 48/16 47/17 45/18 46/19 +f 52/16 51/17 49/18 50/19 +f 56/16 54/19 53/18 55/17 +f 60/16 58/19 57/18 59/17 +f 64/16 63/17 61/18 62/19 +f 68/16 67/17 65/18 66/19 +f 72/16 70/19 69/18 71/17 +f 76/16 74/19 73/18 75/17 +f 80/16 79/17 77/18 78/19 +f 84/16 83/17 81/18 82/19 +f 88/16 86/19 85/18 87/17 +f 92/16 90/19 89/18 91/17 +f 96/16 95/17 93/18 94/19 +f 100/16 99/17 97/18 98/19 +f 104/16 102/19 101/18 103/17 +f 108/16 106/19 105/18 107/17 +f 112/16 111/17 109/18 110/19 +f 116/16 115/17 113/18 114/19 +f 120/16 118/19 117/18 119/17 +f 124/16 122/19 121/18 123/17 +f 128/16 127/17 125/18 126/19 +f 132/16 131/17 129/18 130/19 +f 136/16 134/19 133/18 135/17 +f 140/16 138/19 137/18 139/17 diff --git a/resources/assets/relocation/textures/obj/framebkp.blend b/resources/assets/relocation/textures/obj/framebkp.blend new file mode 100644 index 0000000..68c2cde Binary files /dev/null and b/resources/assets/relocation/textures/obj/framebkp.blend differ diff --git a/resources/assets/relocation/textures/obj/mc_temp.blend b/resources/assets/relocation/textures/obj/mc_temp.blend new file mode 100644 index 0000000..b35d6c4 Binary files /dev/null and b/resources/assets/relocation/textures/obj/mc_temp.blend differ diff --git a/resources/dependancies.info b/resources/dependancies.info new file mode 100644 index 0000000..03090fc --- /dev/null +++ b/resources/dependancies.info @@ -0,0 +1,6 @@ +[{ + "repo": "http://files.minecraftforge.net/maven/codechicken/CodeChickenLib/@MC_VERSION@-@CCL_VERSION@/", + "file": "CodeChickenLib-@MC_VERSION@-@CCL_VERSION@-universal.jar", + "dev": "CodeChickenLib-@MC_VERSION@-@CCL_VERSION@-dev.jar", + "class": "codechicken.lib.asm.ASMHelper" +}] \ No newline at end of file diff --git a/resources/mcmod.info b/resources/mcmod.info new file mode 100644 index 0000000..3e00c65 --- /dev/null +++ b/resources/mcmod.info @@ -0,0 +1,18 @@ +[ +{ + "modid": "ForgeRelocation", + "name": "ForgeRelocation", + "description":"Move blocks from one place to another", + "version": "@VERSION@.@BUILD_NUMBER@", + "mcversion": "@MC_VERSION@", + "url": "...", + "authors": [ "MrTJP" ], + "credits": "", + "logoFile": "", + "screenshots": [], + "requiredMods": [ "Forge", "MrTJPCoreMod" ], + "dependencies": [ "MrTJPCoreMod" ], + "dependants" : [ "RelocationFMP" ], + "useDependencyInformation": true +} +] \ No newline at end of file diff --git a/src/mrtjp/relocation/api/IFrame.java b/src/mrtjp/relocation/api/IFrame.java new file mode 100644 index 0000000..624dc83 --- /dev/null +++ b/src/mrtjp/relocation/api/IFrame.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation.api; + +import net.minecraft.world.World; + +/** + * Interface that can be implemented on Tile Entities or Blocks that wish to + * act as frames, which are the blocks that stick together and form a + * moving structure when moved with a motor. No other action besides + * implementation of this interface is needed for the block to function. + */ +public interface IFrame +{ + /** + * Used to check if the given side on this frame block is sticky. + * Sticky sides will allow other frames to stick to this one, + * as well as other blocks. + * + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + * @param side The side of the block, as a ForgeDirection + * @return True if the side can latch on to another block. + */ + public boolean latchSide(World w, int x, int y, int z, int side); +} \ No newline at end of file diff --git a/src/mrtjp/relocation/api/IFrameInteraction.java b/src/mrtjp/relocation/api/IFrameInteraction.java new file mode 100644 index 0000000..f097237 --- /dev/null +++ b/src/mrtjp/relocation/api/IFrameInteraction.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation.api; + +import net.minecraft.world.World; + +/** + * Class used instead of {@link IFrame} to add frame capabilities + * to a block without having the block or tile in that location + * implement the IFrame interface. This class must be registered in + * the {@link RelocationAPI}. + */ +public abstract class IFrameInteraction implements IFrame +{ + /** + * Check to see if this interaction can be executed at the given + * coordinates. + * + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + * @return True if this interaction is valid for the given + * location. + */ + public abstract boolean canInteract(World w, int x, int y, int z); +} diff --git a/src/mrtjp/relocation/api/IFramePlacement.java b/src/mrtjp/relocation/api/IFramePlacement.java new file mode 100644 index 0000000..ad9039e --- /dev/null +++ b/src/mrtjp/relocation/api/IFramePlacement.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation.api; + +import codechicken.lib.vec.Vector3; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +/** + * A utility interface used by the frame ItemBlock when placing. + * It can be used to add interactions to the default frame block + * placement. This class can be registered through the + * {@link RelocationAPI}. + */ +public interface IFramePlacement +{ + /** + * Called sequentially on all registered IFrameBlockPlacements on + * the frame item block's onItemUse function, until one returns true. + * @param item + * @param player + * @param world + * @param x + * @param y + * @param z + * @param side + * @param hit + * @return + */ + public boolean onItemUse(ItemStack item, EntityPlayer player, World world, int x, int y, int z, int side, Vector3 hit); +} \ No newline at end of file diff --git a/src/mrtjp/relocation/api/ITileMover.java b/src/mrtjp/relocation/api/ITileMover.java new file mode 100644 index 0000000..dd4e2e4 --- /dev/null +++ b/src/mrtjp/relocation/api/ITileMover.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation.api; + +import net.minecraft.world.World; + +/** + * Interface which when implemented manages the movement of blocks and tiles that are + * registered to it. This class should be registered through the {@link RelocationAPI}. + */ +public interface ITileMover +{ + /** + * Used to check if the block at the given position can move. This + * method is only called if the specified block is tied to this + * handler, so there is no need to check if the block is valid + * for this handler. This is called before actually moving. If + * everything is able to move, an animation will start. + * + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + * @return True if the block at the given position is able to move. + */ + public boolean canMove(World w, int x, int y, int z); + + /** + * Method used to actually move the tile. Called after the animation + * has run. This is where you should tell the tile that it is time + * to move, and peform any extra checks or calls. This is called + * on every block in the moved structure sequentially. + * + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + * @param side The ForgeDirection side the structure is moving in. + */ + public void move(World w, int x, int y, int z, int side); + + /** + * Called after all blocks in the group have moved to their + * new locations. This is where you would reload your tile, + * tell it to refresh or reacknowledge its new position. + * + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + */ + public void postMove(World w, int x, int y, int z); +} \ No newline at end of file diff --git a/src/mrtjp/relocation/api/RelocationAPI.java b/src/mrtjp/relocation/api/RelocationAPI.java new file mode 100644 index 0000000..04cbf63 --- /dev/null +++ b/src/mrtjp/relocation/api/RelocationAPI.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation.api; + +import net.minecraft.block.Block; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +/** + * Central API class for Relocation. + * If Relocation is installed, the appropriate field will contain an + * implementor of these methods. + *

+ * It is recommended that mods access this class within a soft dependency class. + */ +public abstract class RelocationAPI +{ + /** + * This field will contain an implementor of this API if Relocation is installed. + */ + public static RelocationAPI instance; + + /** + * Used to register a {@link ITileMover} class that manages the movement of certain tiles. + * This method must be called during FML pre-initialization. + * + * @param name The name of the mover that will be used to assign blocks to it. + * @param desc The description of what this mover is used for or why it is included. + * @param mover The {@link ITileMover} to register. + */ + public abstract void registerTileMover(String name, String desc, ITileMover mover); + + /** + * Used to register an in-game block to a specific {@link ITileMover} which are registered + * with the method above. This method adds the key-value pairs similar to the config, + * but their assignments can be changed from the config file if you would like. + * This method must be called during FML pre-initialization. + * + * @param key The mod or block key regex. This works the same way it does from the + * config file: + * Possible keys: + * default - to assign default mover + * mod: - to assign every block from a mod + * : - to assign block from a mod for every meta + :m - to assign block from mod for specific meta + * + * @param value The name of the mover to assign this block. A list of all available + * movers will show up in the configs. + */ + public abstract void registerPreferredMover(String key, String value); + + /** + * Used to register an in-game block to a specific {@link ITileMover} which are registered + * with the method above. This method adds the key-value pairs similar to the config. These + * assignments are manatory, and blocks that are registered will be locked to the specified + * mover, and it cannot be changed from the config. + * This method must be called during FML pre-initialization. + * + * @param key The mod or block key regex. This works the same way it does from the + * config file: + * Possible keys: + * default - to assign default mover + * mod: - to assign every block from a mod + * : - to assign block from a mod for every meta + :m - to assign block from mod for specific meta + * + * @param value The name of the mover to assign this block. A list of all available + * movers will show up in the configs. + */ + public abstract void registerMandatoryMover(String key, String value); + + /** + * Used to register a custom placment that can define how a frame is placed. + * This is useful for cases such as if the frame is placed on a Multipart from + * the Forge Multipart API, this placement property can perform special actions + * that would add the frame to the multipart tile. + * + * @param placement The custom frame placement to register. + */ + public abstract void registerFramePlacement(IFramePlacement placement); + + /** + * Used to register a {@link IFrameInteraction}, which is a class that + * can be used to add frame-like properties to any block. + * + * @param interaction The interaction to register. + */ + public abstract void registerFrameInteraction(IFrameInteraction interaction); + + /** + * Getter for the instance variable of the Frame block. Used if external + * implementations need the block. (i.e. registration purposes) + * + * @return The frame block. + */ + public abstract Block getFrameBlock(); + + /** + * Getter for the instance variable of the Motor block. Used if external + * implementations need the block. (i.e. registration purposes) + * + * @return The motor block. + */ + public abstract Block getMotorBlock(); + + + /** Utilities - used for silent block manipulation. Caution: May be removed.. **/ + + /** + * Used to set a block in the world to the given block without + * alerting the world of the change. + * + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + * @param b The block. + * @param meta Block metadata + */ + public abstract void uncheckedSetBlock(World w, int x, int y, int z, Block b, int meta); + + /** + * Used to set a tile entity in the world without alerting the + * world of the change. + * + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + * @param te The TileEntity. + */ + public abstract void uncheckedSetTileEntity(World w, int x, int y, int z, TileEntity te); + + /** + * Used to remove a tile entity in the world without alerting the + * world of the change. + * + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + */ + public abstract void uncheckedRemoveTileEntity(World w, int x, int y, int z); + + /** + * Used to retreive a tile from a world without alerting the world + * that the tile was fetched from memory. + * + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + * @return The TileEnity at the given coordinates + */ + public abstract TileEntity uncheckedGetTileEntity(World w, int x, int y, int z); + + + /** + * Tessellates the frame model at the given coordinates. Useful for making + * your block look like the default frame block. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + */ + public abstract void renderFrame(double x, double y, double z); + + /** + * Raytrace a frame block at the given world coords with start and end + * points of a ray. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + * @param start The start point of the ray + * @param end The end point of the ray + * @return The object position if anything from the frame model was hit. + */ + public abstract MovingObjectPosition raytraceFrame(double x, double y, double z, Vec3 start, Vec3 end); +} diff --git a/src/mrtjp/relocation/api/package-info.java b/src/mrtjp/relocation/api/package-info.java new file mode 100644 index 0000000..f7c8d21 --- /dev/null +++ b/src/mrtjp/relocation/api/package-info.java @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ + +@API(owner = "ForgeRelocation", provides = "ForgeRelocation|API", apiVersion = "0.0.1a") +package mrtjp.relocation.api; + +import cpw.mods.fml.common.API; \ No newline at end of file diff --git a/src/mrtjp/relocation/asm/Transformer.scala b/src/mrtjp/relocation/asm/Transformer.scala new file mode 100644 index 0000000..c955362 --- /dev/null +++ b/src/mrtjp/relocation/asm/Transformer.scala @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2015. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation.asm + +import java.util.{Map => JMap} + +import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper.{INSTANCE => mapper} +import cpw.mods.fml.relauncher.{IFMLCallHook, IFMLLoadingPlugin} +import mrtjp.relocation.RelocationMod +import net.minecraft.launchwrapper.{IClassTransformer, Launch} +import org.objectweb.asm.Opcodes._ +import org.objectweb.asm.tree._ +import org.objectweb.asm.{ClassReader, ClassWriter} + +import scala.collection.JavaConversions._ + +/** + * Add "Dfml.coreMods.load=mrtjp.relocation.asm.RelocationPlugin" to launch configs + * to enable in a development workspace. + */ +@IFMLLoadingPlugin.TransformerExclusions(value = Array("mrtjp.relocation.asm", "scala")) +class RelocationPlugin extends IFMLLoadingPlugin with IFMLCallHook +{ + override def getASMTransformerClass = Array("mrtjp.relocation.asm.Transformer") + override def getSetupClass = "mrtjp.relocation.asm.RelocationPlugin" + override def getModContainerClass = null + override def getAccessTransformerClass = null + override def injectData(data:JMap[String, AnyRef]){} + override def call():Void = null +} + +class Transformer extends IClassTransformer +{ + type MethodChecker = (String, MethodNode) => Boolean + type InsTransformer = MethodNode => Unit + + lazy val deobfEnv = (Launch.blackboard get "fml.deobfuscatedEnvironment").asInstanceOf[Boolean] + lazy val blockClass = mapper.unmap("net/minecraft/block/Block") + lazy val teClass = mapper.unmap("net/minecraft/tileentity/TileEntity") + + def transformBlockRender(m:MethodNode) + { + val old = m.instructions.toArray.collectFirst{ case i:MethodInsnNode => i }.get + val list = new InsnList + list.add(new VarInsnNode(ILOAD, 2)) + list.add(new VarInsnNode(ILOAD, 3)) + list.add(new VarInsnNode(ILOAD, 4)) + list.add(new MethodInsnNode(INVOKESTATIC, "mrtjp/relocation/ASMHacks", + "getRenderType", "(Lnet/minecraft/block/Block;III)I", false)) + m.instructions.insert(old, list) + m.instructions.remove(old) + } + + def transformTERender(m:MethodNode) + { + val old = m.instructions.toArray.collect{ case i:MethodInsnNode => i }.last + m.instructions.insert(old, new InsnNode(POP)) + m.instructions.insert(old, new MethodInsnNode(INVOKESTATIC, + "mrtjp/relocation/ASMHacks", "renderTileEntityAt", old.desc, false)) + m.instructions.remove(old) + } + + val classData = Map[String, (MethodChecker, MethodChecker, InsTransformer)]( + "net.minecraft.client.renderer.RenderBlocks" -> (( + (_:String, m:MethodNode) => m.name == "renderBlockByRenderType", + (n:String, m:MethodNode) => mapper.mapMethodName(n, m.name, m.desc) == "func_147805_b", + transformBlockRender _ + )), + "net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher" -> (( + (_:String, m:MethodNode) => m.name == "renderTileEntity", + (n:String, m:MethodNode) => mapper.mapMethodName(n, m.name, m.desc) == "func_147544_a", + transformTERender _ + )) + ) + + var matched = Set[String]() + + override def transform(name:String, tName:String, data:Array[Byte]) = + { + if (classData.keys.contains(tName) && !matched.contains(tName)) + { + RelocationMod.log.info(s"transforming: $tName") + val (ch1, ch2, tr) = classData(tName) + + val node = new ClassNode + val reader = new ClassReader(data) + reader.accept(node, 0) + + for (m@(_m:MethodNode) <- node.methods) + if ((deobfEnv && ch1(name, m)) || (!deobfEnv && ch2(name, m))) + { + RelocationMod.log.info(s"$name $tName ${m.name} ${m.desc}") + tr(m) + } + + matched += tName + + val writer = new ClassWriter(ClassWriter.COMPUTE_MAXS) + node.accept(writer) + writer.toByteArray + } + else data + } +} \ No newline at end of file diff --git a/src/mrtjp/relocation/fractalations.scala b/src/mrtjp/relocation/fractalations.scala new file mode 100644 index 0000000..f43051a --- /dev/null +++ b/src/mrtjp/relocation/fractalations.scala @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.vec.{BlockCoord, Vector3} +import mrtjp.core.block.{InstancedBlockTile, InstancedBlock} +import mrtjp.core.world.WorldLib +import net.minecraft.block.Block +import net.minecraft.block.material.Material +import net.minecraft.init.Blocks +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.world.{IBlockAccess, World} + +import scala.collection.mutable.{Set => MSet} + +class BlockMovingRow extends InstancedBlock("relocation.BlockMovingRow", Material.iron) +{ + setHardness(-1F) + setStepSound(Block.soundTypeGravel) + setCreativeTab(null) + addSingleTile(classOf[TileMovingRow]) + + override def createTileEntity(world:World, meta:Int) = new TileMovingRow(None) + + override def setBlockBoundsBasedOnState(world:IBlockAccess, x:Int, y:Int, z:Int) + { + Option(world.getTileEntity(x, y, z)).collect + { + case te:TileMovingRow if te.parentPos.isDefined => + Option(WorldLib.getTileEntity(te.getWorldObj, te.parentPos.get)).map(p => (te, p)) + }.flatten.collect + { + case (te, parent:TileMotor) => + val pos = new BlockCoord(te).offset(parent.getMoveDir^1) + val block = world.getBlock(pos.x, pos.y, pos.z) + if (parent.offset == 0 || block == null) setBlockBounds(.5F, .5F, .5F, .5F, .5F, .5F) + else + { + val shift = (16-parent.offset).toFloat/16F + val sh = new Vector3(new BlockCoord().offset(parent.getMoveDir))*shift + setBlockBounds( + (block.getBlockBoundsMinX-sh.x).toFloat, + (block.getBlockBoundsMinY-sh.y).toFloat, + (block.getBlockBoundsMinZ-sh.z).toFloat, + (block.getBlockBoundsMaxX-sh.x).toFloat, + (block.getBlockBoundsMaxY-sh.y).toFloat, + (block.getBlockBoundsMaxZ-sh.z).toFloat) + } + } + } + + override def getCollisionBoundingBoxFromPool(world:World, x:Int, y:Int, z:Int) = + { + setBlockBoundsBasedOnState(world, x, y, z) + Option(world.getTileEntity(x, y, z)).collect + { + case te:TileMovingRow if te.parentPos.isDefined => + Option(WorldLib.getTileEntity(te.getWorldObj, te.parentPos.get)) + }.flatten.collect + { + case te:TileMotor => te.getAabb(new BlockCoord(x, y, z)) + }.orNull + } +} + +class TileMovingRow(var parentPos:Option[BlockCoord] = None) extends InstancedBlockTile +{ + override def update(){super.update(); checkLocation()} + override def updateClient(){super.updateClient(); checkLocation()} + + def checkLocation() + { + def voidBlock(){world.setBlock(xCoord, yCoord, zCoord, Blocks.air, 0, 3)} + parentPos match + { + case Some(e) => WorldLib.getTileEntity(world, e) match + { + case te:TileMotor => + case _ => voidBlock() + } + case None => voidBlock() + } + } + + override def getBlock = RelocationMod.blockMovingRow + + override def save(tag:NBTTagCompound) + { + super.save(tag) + val (x, y, z) = parentPos match + { + case Some(bc) => (bc.x, bc.y, bc.z) + case None => (0, -1, 0) + } + tag.setIntArray("pos", Array(x, y, z)) + } + + override def load(tag:NBTTagCompound) + { + super.load(tag) + parentPos = Option(new BlockCoord(tag.getIntArray("pos"))) + } + + override def readDesc(in:MCDataInput) + { + super.readDesc(in) + parentPos = Option(in.readCoord()) + } + + override def writeDesc(out:MCDataOutput) + { + super.writeDesc(out) + val (x, y, z) = parentPos match + { + case Some(bc) => (bc.x, bc.y, bc.z) + case None => (0, -1, 0) + } + out.writeCoord(x, y, z) + } +} + +case class BlockRow(pos:BlockCoord, moveDir:Int, size:Int) +{ + def preMove(w:World, offset:RenderPos) + { + for (i <- 1 to size) + { + val bc = pos.copy.offset(moveDir^1, i) + MovementManager.addMoving(w, bc, offset) + } + } + + def doMove(w:World) + { + if (pos.y < 0 || pos.y >= 256) return + + w.removeTileEntity(pos.x, pos.y, pos.z) + WorldLib.uncheckedSetBlock(w, pos.x, pos.y, pos.z, Blocks.air, 0) //Remove movement block + + for (i <- 1 to size) + { + val c = pos.copy.offset(moveDir^1, i) + MovingTileRegistry.move(w, c.x, c.y, c.z, moveDir) + } + } + + def postMove(w:World) + { + for (i <- 0 until size) + { + val c = pos.copy.offset(moveDir^1, i) + MovingTileRegistry.postMove(w, c.x, c.y, c.z) + } + } + + def endMove(w:World) + { + for (i <- 0 to size) + MovementManager.removeMoving(w, pos.copy.offset(moveDir^1, i)) + } + + def cacheChanges(w:World, changes:MSet[BlockCoord]) + { + for (i <- 0 to size) + { + val c = pos.copy.offset(moveDir^1, i) + changes += c + for (s <- 0 until 6; s1 <- 0 until 6 if s1 != (s^1)) + changes += c.copy.offset(s).offset(s1) + } + } +} \ No newline at end of file diff --git a/src/mrtjp/relocation/frame.scala b/src/mrtjp/relocation/frame.scala new file mode 100644 index 0000000..777f26f --- /dev/null +++ b/src/mrtjp/relocation/frame.scala @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation + +import codechicken.lib.vec.{Cuboid6, Vector3} +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.core.block.{InstancedBlock, ItemBlockCore} +import mrtjp.core.resource.SoundLib +import mrtjp.relocation.api.{IFrame, IFramePlacement} +import net.minecraft.block.Block +import net.minecraft.block.material.Material +import net.minecraft.creativetab.CreativeTabs +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.item.ItemStack +import net.minecraft.util.Vec3 +import net.minecraft.world.{IBlockAccess, World} +import net.minecraftforge.common.util.ForgeDirection + +class BlockFrame extends InstancedBlock("relocation.blockframe", Material.wood) with IFrame +{ + setResistance(5.0F) + setHardness(2.0F) + setStepSound(Block.soundTypeWood) + setCreativeTab(CreativeTabs.tabTransport) + + override def getItemBlockClass = classOf[ItemBlockFrame] + + override def latchSide(w:World, x:Int, y:Int, z:Int, side:Int) = true + + override def isSideSolid(w:IBlockAccess, x:Int, y:Int, z:Int, side:ForgeDirection) = false + + override def collisionRayTrace(world:World, x:Int, y:Int, z:Int, start:Vec3, end:Vec3) = + Utils.raytraceFrame(x, y, z, start, end) + + @SideOnly(Side.CLIENT) + override def getSelectedBoundingBoxFromPool(w:World, x:Int, y:Int, z:Int) = + Cuboid6.full.copy.expand(0.002).add(new Vector3(x, y, z)).toAABB +} + +object ItemBlockFrame +{ + var placements = Seq[IFramePlacement]() +} + +class ItemBlockFrame(b:Block) extends ItemBlockCore(b) +{ + override def onItemUse(item:ItemStack, player:EntityPlayer, world:World, x:Int, y:Int, z:Int, side:Int, hitX:Float, hitY:Float, hitZ:Float):Boolean = + { + if (ItemBlockFrame.placements.exists(_.onItemUse(item, player, world, x, y, z, + side, new Vector3(hitX, hitY, hitZ)))) + { + SoundLib.playBlockPlacement(world, x, y, z, field_150939_a) + true + } + else super.onItemUse(item, player, world, x, y, z, side, hitX, hitY, hitZ) + } + + override def func_150936_a(world:World, x:Int, y:Int, z:Int, side:Int, player:EntityPlayer, stack:ItemStack) = true +} \ No newline at end of file diff --git a/src/mrtjp/relocation/hacks.scala b/src/mrtjp/relocation/hacks.scala new file mode 100644 index 0000000..45a3506 --- /dev/null +++ b/src/mrtjp/relocation/hacks.scala @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation + +import codechicken.lib.vec.{BlockCoord, Vector3} +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.core.math.MathLib +import net.minecraft.block.Block +import net.minecraft.client.Minecraft +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher +import net.minecraft.tileentity.TileEntity + +object ASMHacks +{ + @SideOnly(Side.CLIENT) + def renderTileEntityAt(te:TileEntity, x:Double, y:Double, z:Double, tick:Float):Unit = + { + if (MovementManager.isMoving(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord)) + { + val o = MovementManager.getData(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord) + val vec = o.vec.copy+new Vector3(new BlockCoord().offset(o.moveDir))*tick/16F + TileEntityRendererDispatcher.instance.renderTileEntityAt(te, + x+MathLib.clamp(-1F, 1F, vec.x.toFloat), + y+MathLib.clamp(-1F, 1F, vec.y.toFloat), + z+MathLib.clamp(-1F, 1F, vec.z.toFloat), tick) + } + else TileEntityRendererDispatcher.instance.renderTileEntityAt(te, x, y, z, tick) + } + + @SideOnly(Side.CLIENT) + def getRenderType(block:Block, x:Int, y:Int, z:Int):Int = + { + if (MovingRenderer.renderHack && MovementManager.isMoving(Minecraft.getMinecraft.theWorld, x, y, z)) -1 + else block.getRenderType + } +} \ No newline at end of file diff --git a/src/mrtjp/relocation/hooks.scala b/src/mrtjp/relocation/hooks.scala new file mode 100644 index 0000000..ea3a291 --- /dev/null +++ b/src/mrtjp/relocation/hooks.scala @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation + +import codechicken.lib.vec.{BlockCoord, Vector3} +import cpw.mods.fml.common.eventhandler.SubscribeEvent +import cpw.mods.fml.common.gameevent.TickEvent +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.core.math.MathLib +import net.minecraft.block.Block +import net.minecraft.client.Minecraft +import net.minecraft.client.renderer.texture.TextureMap +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher +import net.minecraft.client.renderer.{OpenGlHelper, RenderBlocks, RenderHelper, Tessellator} +import net.minecraft.world.{EnumSkyBlock, IBlockAccess, World} +import net.minecraftforge.client.event.RenderWorldLastEvent +import net.minecraftforge.common.util.ForgeDirection +import org.lwjgl.opengl.GL11._ + +object MovingRenderer +{ + var partialTickTime = 0.0f + var isRendering = false + var renderHack = true + + def mc = Minecraft.getMinecraft + def world = mc.theWorld + def tes = Tessellator.instance + + var oldWorld:World = null + var renderBlocks:RenderBlocks = null + + def render(x:Int, y:Int, z:Int, d:RenderPos, tick:Float) + { + val oldOcclusion = mc.gameSettings.ambientOcclusion + mc.gameSettings.ambientOcclusion = 0 + + val block = world.getBlock(x, y, z) + if (block == null) return + + val engine = TileEntityRendererDispatcher.instance.field_147553_e + if (engine != null) engine.bindTexture(TextureMap.locationBlocksTexture) + mc.entityRenderer.enableLightmap(partialTickTime) + + val light = world.getLightBrightnessForSkyBlocks(x, y, z, block.getLightValue(world, x, y, z)) + val l1 = light%65536 + val l2 = light/65536 + + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, l1, l2) + glColor4f(0, 0, 0, 0) + RenderHelper.disableStandardItemLighting() + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + glEnable(GL_BLEND) + glDisable(GL_CULL_FACE) + glShadeModel(if (Minecraft.isAmbientOcclusionEnabled) GL_SMOOTH else GL_FLAT) + + val vec = d.vec.copy+new Vector3(new BlockCoord().offset(d.moveDir))*tick/16F + for (pass <- 0 to 1) + { + tes.startDrawingQuads() + tes.setTranslation( + -TileEntityRendererDispatcher.staticPlayerX+MathLib.clamp(-1F, 1F, vec.x.toFloat), + -TileEntityRendererDispatcher.staticPlayerY+MathLib.clamp(-1F, 1F, vec.y.toFloat), + -TileEntityRendererDispatcher.staticPlayerZ+MathLib.clamp(-1F, 1F, vec.z.toFloat)) + tes.setColorOpaque(1, 1, 1) + + block.getRenderBlockPass + if (block.canRenderInPass(pass)) + { + renderHack = false + renderBlocks.renderBlockByRenderType(block, x, y, z) + renderHack = true + } + + tes.setTranslation(0, 0, 0) + tes.draw() + } + RenderHelper.enableStandardItemLighting() + mc.entityRenderer.disableLightmap(partialTickTime) + mc.gameSettings.ambientOcclusion = oldOcclusion + } + + @SubscribeEvent + def onRenderWorld(e:RenderWorldLastEvent) + { + if (oldWorld != world) + { + oldWorld = world + renderBlocks = new MovingRenderBlocks(new MovingWorld(world)) + renderBlocks.renderAllFaces = true + MovementManager.clientMap.clear() + } + MovementManager.clientMap.synchronized + { + val it = MovementManager.clientMap.iterator + while (it.hasNext) + { + it.advance() + val k = it.key() + val v = it.value() + import mrtjp.core.world.WorldLib.{unpackX, unpackY, unpackZ} + render(unpackX(k), unpackY(k), unpackZ(k), v, partialTickTime) + } + } + } + + def onPreRenderTick(time:Float) + { + isRendering = true + partialTickTime = time + } + + def onPostRenderTick() + { + isRendering = false + } +} + +object RenderTicker +{ + @SubscribeEvent + def onRenderTick(e:TickEvent.RenderTickEvent) + { + if (e.phase == TickEvent.Phase.START) + MovingRenderer.onPreRenderTick(e.renderTickTime) + else MovingRenderer.onPostRenderTick() + } +} + +class RenderPos(val vec:Vector3, var moveDir:Int) +{ + def this(x:Float, y:Float, z:Float, moveDir:Int) = this(new Vector3(x, y, z), moveDir) + + def x = vec.x.toFloat + def y = vec.y.toFloat + def z = vec.z.toFloat +} + +@SideOnly(Side.CLIENT) +class MovingRenderBlocks(w:IBlockAccess) extends RenderBlocks(w) +{ + override def renderStandardBlock(block:Block, x:Int, y:Int, z:Int) = + { + import mrtjp.relocation.MovementManager.eps + if (MovementManager.isMoving(Minecraft.getMinecraft.theWorld, x, y, z)) + { + if (renderMinX == 0.0D) renderMinX += eps + if (renderMinY == 0.0D) renderMinY += eps + if (renderMinZ == 0.0D) renderMinZ += eps + if (renderMaxX == 1.0D) renderMaxX -= eps + if (renderMaxY == 1.0D) renderMaxY -= eps + if (renderMaxZ == 1.0D) renderMaxZ -= eps + } + super.renderStandardBlock(block, x, y, z) + } +} + +class MovingWorld(val world:World) extends IBlockAccess +{ + override def getBlock(x:Int, y:Int, z:Int) = world.getBlock(x, y, z) + + override def getTileEntity(x:Int, y:Int, z:Int) = world.getTileEntity(x, y, z) + + def computeLightValue(x:Int, y:Int, z:Int, tpe:EnumSkyBlock) = + { + (for (s <- 0 until 6; c = new BlockCoord(x, y, z).offset(s)) + yield world.getSavedLightValue(tpe, c.x, c.y, c.z)).max + } + + @SideOnly(Side.CLIENT) + override def getLightBrightnessForSkyBlocks(x:Int, y:Int, z:Int, light:Int) = + MovementManager.isMoving(Minecraft.getMinecraft.theWorld, x, y, z) match + { + case true => + val l1 = computeLightValue(x, y, z, EnumSkyBlock.Sky) + val l2 = computeLightValue(x, y, z, EnumSkyBlock.Block) + l1<<20|Seq(l2, light).max<<4 + case false => world.getLightBrightnessForSkyBlocks(x, y, z, light) + } + + override def getBlockMetadata(x:Int, y:Int, z:Int) = world.getBlockMetadata(x, y, z) + + @SideOnly(Side.CLIENT) + override def isAirBlock(x:Int, y:Int, z:Int) = world.isAirBlock(x, y, z) + + @SideOnly(Side.CLIENT) + override def getBiomeGenForCoords(x:Int, z:Int) = world.getBiomeGenForCoords(x, z) + + @SideOnly(Side.CLIENT) + override def getHeight = world.getHeight + + @SideOnly(Side.CLIENT) + override def extendedLevelsInChunkCache() = world.extendedLevelsInChunkCache() + + override def isBlockProvidingPowerTo(x:Int, y:Int, z:Int, side:Int) = + world.isBlockProvidingPowerTo(x, y, z, side) + + override def isSideSolid(x:Int, y:Int, z:Int, side:ForgeDirection, _default:Boolean) = + world.isSideSolid(x, y, z, side, _default) +} \ No newline at end of file diff --git a/src/mrtjp/relocation/mod.scala b/src/mrtjp/relocation/mod.scala new file mode 100644 index 0000000..7bedf6b --- /dev/null +++ b/src/mrtjp/relocation/mod.scala @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation + +import codechicken.lib.vec.Vector3 +import cpw.mods.fml.common.Mod +import cpw.mods.fml.common.event.{FMLInitializationEvent, FMLPostInitializationEvent, FMLPreInitializationEvent} +import mrtjp.core.data.{ModConfig, SpecialConfigGui, TModGuiFactory} +import mrtjp.core.world.WorldLib +import mrtjp.relocation.MovingTileRegistry._ +import mrtjp.relocation.api._ +import net.minecraft.block.Block +import net.minecraft.client.gui.GuiScreen +import net.minecraft.tileentity.TileEntity +import net.minecraft.util.Vec3 +import net.minecraft.world.World +import org.apache.logging.log4j.LogManager + +@Mod(modid = RelocationMod.modID, useMetadata = true, modLanguage = "scala", guiFactory = "mrtjp.relocation.GuiConfigFactory") +object RelocationMod +{ + RelocationAPI.instance = RelocationAPI_Impl + + final val modID = "ForgeRelocation" + final val modName = "ForgeRelocation" + final val version = "@VERSION@" + final val buildnumber = "@BUILD_NUMBER@" + + val log = LogManager.getFormatterLogger(modID) + + var blockMovingRow:BlockMovingRow = _ + var blockMotor:BlockMotor = _ + var blockFrame:Block with IFrame = _ + + @Mod.EventHandler + def preInit(event:FMLPreInitializationEvent) + { + RelocationProxy.preinit() + } + + @Mod.EventHandler + def init(event:FMLInitializationEvent) + { + RelocationAPI_Impl.isPreInit = false + RelocationProxy.init() + } + + @Mod.EventHandler + def postInit(event:FMLPostInitializationEvent) + { + RelocationProxy.postinit() + } +} + +object RelocationConfig extends ModConfig("ForgeRelocation") +{ + var moveLimit = 2048 + var mCap = 1000.0D + var mInitial = 40.0D + var mLoad = 10.0D + + var simpleModel = true + + var moverMap = Array( + "default -> saveload" + ) + + var setMap = Array( + "bed -> bed", + "wooden_door -> wooden_door", + "iron_door -> iron_door" + ) + + override protected def initValues() + { + val general = new BaseCategory("General", "Basic settings") + moveLimit = general.put("moveLimit", moveLimit, "Maxumum amount of blocks that can be moved at once.") + + val renders = new BaseCategory("Rendering", "Settings related to block rendering") + simpleModel = renders.put("Simple frame model", simpleModel, "Set to false to use a more complex version of the frame model. Looks better but requires more resources.") + + val movers = new BaseCategory("Tile Movers", buildMoverDesc) + moverMap = movers.put("mover registry", moverMap) + moverMap = movers.put("mover registry", parseAndSetMovers(moverMap), true) + + val sets = new BaseCategory("Latched Sets", buildLatchSetsDesc) + setMap = sets.put("latch registry", setMap) + parseAndAddLatchSets(setMap) + + val power = new BaseCategory("Power", "Settings that manage the power use of motors. The cost of moving n blocks is initial + n * load") + mCap = power.put("capacity", mCap, "The total power capacity for a motor.") + mInitial = power.put("initial", mInitial) + mLoad = power.put("load", mLoad) + } + + def buildMoverDesc:String = + { + var s = "Used to configure which registered Tile Mover is used for a block. Key-Value pairs are defined using \n" + + "the syntax key -> value. \n" + s += "Most blocks are configurable, but some mods may have opted to lock which handlers can be used for its \n" + + "blocks.\n" + s += "Possible keys: \n" + s += " 'default' - to assign default handler. \n" + s += " 'mod:' - to assign every block from a mod. \n" + s += " ':' - to assign block from a mod for every meta. \n" + s += " ':m' - to assign block from mod for specific meta. \n" + + s += "\nAvailable tile movers:\n" + for ((k, v) <- MovingTileRegistry.moverDescMap) + s += " '"+k+"' - "+v+"\n" + + if (mandatoryMovers.nonEmpty) + { + s += "\nMovers locked via API:\n" + for ((k, v) <- MovingTileRegistry.mandatoryMovers) + s += " "+k+" -> "+v+"\n" + } + + s + } + + def buildLatchSetsDesc:String = + { + var s = "Used to define which pairs of blocks will be stuck together. \n" + s += "Latched sets will always move in pairs, even if only one of them are actually connected to a block. \n" + s += "'block1 -> block2' means that if block1 is moved, any block2 connected to it will also move. \n" + s += "However, moving block2 does not move block1. To do that, you must also register block2 -> block1. \n" + s += "Sets are defined using the syntax of key -> value. \n" + s += "Possible keys and values:\n" + s += " ':' - to assign block from a mod for every meta. \n" + s += " ':m' - to assign block from mod for specific meta. \n" + s + } +} + +class RelocationConfigGui(parent:GuiScreen) extends SpecialConfigGui(parent, "RelocationTestConfig", RelocationConfig.config) + +class GuiConfigFactory extends TModGuiFactory +{ + override def mainConfigGuiClass() = classOf[RelocationConfigGui] +} + +object RelocationAPI_Impl extends RelocationAPI +{ + var isPreInit = true + + override def registerTileMover(name:String, desc:String, handler:ITileMover) = + { + assert(isPreInit) + MovingTileRegistry.registerTileMover(name, desc, handler) + } + + override def registerPreferredMover(key:String, value:String) + { + assert(isPreInit) + MovingTileRegistry.preferredMovers :+= (key, value) + } + + override def registerMandatoryMover(key:String, value:String) + { + assert(isPreInit) + MovingTileRegistry.mandatoryMovers :+= (key, value) + } + + override def registerFramePlacement(placement:IFramePlacement) + { + ItemBlockFrame.placements :+= placement + } + + override def registerFrameInteraction(interaction:IFrameInteraction) + { + MovingTileRegistry.interactionList :+= interaction + } + + override def getFrameBlock = RelocationMod.blockFrame + + override def getMotorBlock = RelocationMod.blockMotor + + override def uncheckedRemoveTileEntity(w:World, x:Int, y:Int, z:Int) + { + WorldLib.uncheckedRemoveTileEntity(w, x, y, z) + } + + override def uncheckedSetBlock(w:World, x:Int, y:Int, z:Int, b:Block, meta:Int) + { + WorldLib.uncheckedSetBlock(w, x, y, z, b, meta) + } + + override def uncheckedGetTileEntity(w:World, x:Int, y:Int, z:Int) = + WorldLib.uncheckedGetTileEntity(w, x, y, z) + + override def uncheckedSetTileEntity(w:World, x:Int, y:Int, z:Int, te:TileEntity) + { + WorldLib.uncheckedSetTileEntity(w, x, y, z, te) + } + + override def renderFrame(x:Double, y:Double, z:Double) + { + RenderFrame.render(new Vector3(x, y, z)) + } + + override def raytraceFrame(x:Double, y:Double, z:Double, start:Vec3, end:Vec3) = + Utils.raytraceFrame(x, y, z, start, end) +} \ No newline at end of file diff --git a/src/mrtjp/relocation/motor.scala b/src/mrtjp/relocation/motor.scala new file mode 100644 index 0000000..84f8559 --- /dev/null +++ b/src/mrtjp/relocation/motor.scala @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation + +import java.util.{List => JList} + +import codechicken.lib.data.{MCDataInput, MCDataOutput} +import codechicken.lib.vec.{BlockCoord, Cuboid6, Rotation, Vector3} +import mrtjp.core.block.{InstancedBlock, InstancedBlockTile, TTileOrient} +import mrtjp.core.math.MathLib +import mrtjp.core.world.WorldLib +import net.minecraft.block.Block +import net.minecraft.block.material.Material +import net.minecraft.creativetab.CreativeTabs +import net.minecraft.entity.Entity +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.init.Blocks +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.AxisAlignedBB +import net.minecraft.world.{IBlockAccess, World} +import net.minecraftforge.common.util.ForgeDirection + +import scala.annotation.tailrec +import scala.collection.JavaConversions._ +import scala.collection.immutable.{HashSet, Queue} +import scala.collection.mutable.{HashMap => MHashMap, MultiMap => MMultiMap, Set => MSet} + + +class BlockMotor extends InstancedBlock("relocation.blockmotor", Material.iron) +{ + setHardness(5f) + setResistance(10f) + setStepSound(Block.soundTypeMetal) + setCreativeTab(CreativeTabs.tabTransport) + addSingleTile(classOf[TileMotor]) + + override def isOpaqueCube = false + + override def isSideSolid(world:IBlockAccess, x:Int, y:Int, z:Int, side:ForgeDirection) = true + + override def renderAsNormalBlock = true +} + +class TileMotor extends InstancedBlockTile with TTileOrient with TPowerTile +{ + var rows = HashSet.empty[BlockRow] + var isMoving = false + var offset = 0 + var renderOffset = new RenderPos(0, 0, 0, 6) + + override def onBlockPlaced(side:Int, meta:Int, player:EntityPlayer, stack:ItemStack, hit:Vector3) + { + super.onBlockPlaced(side, meta, player, stack, hit) + setSide(side^1) + setRotation(Rotation.getSidedRotation(player, side^1)) + } + + override def onBlockActivated(player:EntityPlayer, s:Int):Boolean = + { + if (super.onBlockActivated(player, s)) return true + + if (player.isSneaking) setRotation((rotation+1)%4) + else setSide((side+1)%6) + + true + } + + override def onOrientChanged(oldOrient:Int) + { + super.onOrientChanged(oldOrient) + sendOrientUpdate() + } + + override def getBlock = RelocationMod.blockMotor + + override def shouldRefresh(oldB:Block, newB:Block, oldMeta:Int, newMeta:Int, w:World, x:Int, y:Int, z:Int) = + !(oldB eq newB) + + def getMoveDir = absoluteDir((rotation+2)%4) + + def canMoveAllRows:Boolean = + { + if (!world.isBlockIndirectlyGettingPowered(x, y, z)) return false + + val pos = position.offset(side^1) + val block = WorldLib.getBlock(world, pos) + if (block == Blocks.air || MovementManager.isMoving(world, pos) || + !MovingTileRegistry.canMove(world, pos.x, pos.y, pos.z)) + return false + + val blocks = iterate(Queue(pos)) + + val moveEnergy = RelocationConfig.mInitial+RelocationConfig.mLoad*blocks.size + if (getEnergy < moveEnergy-1/4096F) return false + + val map = new MHashMap[(Int, Int), MSet[Int]] with MMultiMap[(Int, Int), Int] + for (b <- blocks) map.addBinding(MathLib.normal(b, getMoveDir), MathLib.basis(b, getMoveDir)) + + val shift = if ((getMoveDir&1) == 1) 1 else -1 + val rows = + { + val builder = Vector.newBuilder[(BlockCoord, Int)] + for (normal <- map.keys) + { + val line = map(normal).toArray + val sline = if (shift == 1) line.sorted else line.sorted(Ordering[Int].reverse) + for ((basis, size) <- MathLib.splitLine(sline, shift)) + { + val c = MathLib.rhrAxis(getMoveDir, normal, basis+shift) + builder += ((c, size)) + } + } + builder.result() + } + + val canMove = (blocks.size <= RelocationConfig.moveLimit) && !rows.exists((pair) => + { + val c = pair._1 + if (c.y < 0 || c.y >= 256) true + else + { + val block = WorldLib.getBlock(world, c) + if (block == null) false + else !block.isReplaceable(world, c.x, c.y, c.z) + } + }) + + if (canMove) + { + isMoving = true + for ((c, size) <- rows) + { + world.setBlock(c.x, c.y, c.z, RelocationMod.blockMovingRow, 0, 3) + WorldLib.getTileEntity(world, c) match + { + case te:TileMovingRow => te.parentPos = Some(position) + case _ => + } + world.markBlockForUpdate(c.x, c.y, c.z) + this.rows += BlockRow(c, getMoveDir, size) + } + markDescUpdate() + } + + if (canMove) setEnergy(getEnergy-moveEnergy) + canMove + } + + @tailrec + private def iterate(open:Seq[BlockCoord], closed:Set[BlockCoord] = Set.empty):Set[BlockCoord] = open match + { + case _ if closed.size > RelocationConfig.moveLimit => closed + case Seq() => closed + case Seq(next, rest@_*) => WorldLib.getBlock(world, next) match + { + case block:Block => + val toCheck = Vector.newBuilder[BlockCoord] + for (s <- 0 until 6) + { + val sticks = MovingTileRegistry.resolveStick(world, next, s) + val to = next.copy.offset(s) + if (sticks && to != position && !closed(to) && !open.contains(to) + && !world.isAirBlock(to.x, to.y, to.z) && !MovementManager.isMoving(world, to) + && MovingTileRegistry.canMove(world, to.x, to.y, to.z)) + toCheck += to + } + iterate(rest++toCheck.result(), closed+next) + case _ => iterate(rest, closed+next) + } + } + + def blocks = + { + val d = getMoveDir + for (r <- rows; i <- 1 to r.size) yield r.pos.copy.offset(d^1, i) + } + + def allBlocks = + { + val d = getMoveDir + for (r <- rows; i <- 0 to r.size) yield r.pos.copy.offset(d^1, i) + } + + def preMove() + { + if (world != null) for (s <- rows) s.preMove(world, renderOffset) + } + + def cycleMove() + { + if (!world.isRemote) writeStream(1).sendToChunk() + + for (r <- rows) r.doMove(world) + for (r <- rows) r.postMove(world) + for (r <- rows) r.endMove(world) + + Utils.rescheduleTicks(world, blocks, allBlocks, getMoveDir) + + val changes = MSet[BlockCoord]() + for (r <- rows) r.cacheChanges(world, changes) + for (bc <- changes) world.notifyBlockOfNeighborChange(bc.x, bc.y, bc.z, Blocks.air) + + Utils.rerenderBlocks(world, blocks) + + rows = HashSet.empty + renderOffset.vec.set(0, 0, 0) + renderOffset.moveDir = 6 + } + + def clientCycleMove() + { + cycleMove() + isMoving = false + offset = 0 + } + + override def update() + { + super.update() + if (offset >= 16) + { + pushEntities() + cycleMove() + isMoving = false + offset = 0 + } + if (offset == 0 && canMoveAllRows) preMove() + pushBlock() + } + + override def updateClient() + { + super.updateClient() + pushBlock() + } + + def pushBlock() + { + if (isMoving && offset <= 16) + { + val dir = getMoveDir + offset += 1 + val shift = offset.toFloat/16.0F + renderOffset.vec.set(new Vector3(new BlockCoord().offset(dir))*shift) + renderOffset.moveDir = dir + } + pushEntities() + } + + def pushEntities() + { + val sh = new Vector3(new BlockCoord().offset(getMoveDir))*1/16D + for (s <- rows; aabb = getAabb(s.pos) if aabb != null) + world.getEntitiesWithinAABBExcludingEntity(null, aabb) match + { + case list:JList[_] => for (e <- list.asInstanceOf[JList[Entity]]) + { + e.moveEntity(0, sh.y max 0, 0) + e.addVelocity(sh.x, sh.y, sh.z) + } + case _ => + } + } + + def getAabb(spos:BlockCoord) = + { + val pos = spos.copy.offset(getMoveDir^1) + val block = world.getBlock(pos.x, pos.y, pos.z) + + if (!isMoving || block == null) null + else + { + val shift = offset.toFloat/16F + block.getCollisionBoundingBoxFromPool(world, pos.x, pos.y, pos.z) match + { + case aabb:AxisAlignedBB => new Cuboid6(aabb).add(new Vector3(new BlockCoord() + .offset(getMoveDir))*shift).toAABB + case _ => null + } + } + } + + def sendOrientUpdate() + { + if (!world.isRemote) + writeStream(2).writeByte(orientation).sendToChunk() + } + + override def read(in:MCDataInput, key:Int) = key match + { + case 1 => clientCycleMove() + case 2 => + orientation = in.readByte() + markRender() + case _ => super.read(in, key) + } + + override def save(tag:NBTTagCompound) + { + super.save(tag) + tag.setBoolean("move", isMoving) + tag.setShort("off", offset.toShort) + + tag.setInteger("length", rows.size) + val rowSeq = rows.toSeq + for (i <- 0 until rows.size) + { + val tag2 = new NBTTagCompound + val s = rowSeq(i) + + tag.setIntArray("pos", Array(s.pos.x, s.pos.y, s.pos.z)) + tag.setByte("dir", getMoveDir.toByte) + tag.setInteger("size", s.size) + + tag.setTag("tag"+i, tag2) + } + } + + override def load(tag:NBTTagCompound) + { + super.load(tag) + isMoving = tag.getBoolean("move") + offset = tag.getShort("off") + + for (i <- 0 until tag.getInteger("length")) + { + val tag2 = tag.getCompoundTag("tag"+i) + rows += BlockRow(new BlockCoord(tag2.getIntArray("pos")), tag2.getByte("dir"), tag2.getInteger("size")) + } + + if (isMoving) preMove() + } + + override def writeDesc(out:MCDataOutput) + { + super.writeDesc(out) + out.writeBoolean(isMoving).writeShort(offset) + + out.writeInt(rows.size) + val bc = position + for (row <- rows) + { + val delta = row.pos.copy.sub(bc) + Seq(delta.x, delta.y, delta.z).foreach(out.writeShort) + out.writeByte(row.moveDir) + out.writeShort(row.size) + } + } + + override def readDesc(in:MCDataInput) + { + super.readDesc(in) + isMoving = in.readBoolean() + offset = in.readUShort() + + val bc = position + for (i <- 0 until in.readInt()) + { + val delta = new BlockCoord(in.readShort(), in.readShort(), in.readShort()) + rows += BlockRow(delta.add(bc), in.readUByte(), in.readUShort()) + } + + if (isMoving) preMove() + } + + override def compressDesc = true +} \ No newline at end of file diff --git a/src/mrtjp/relocation/power.scala b/src/mrtjp/relocation/power.scala new file mode 100644 index 0000000..c71316e --- /dev/null +++ b/src/mrtjp/relocation/power.scala @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation + +import mrtjp.core.block.InstancedBlockTile +import net.minecraft.nbt.NBTTagCompound + +trait TPowerTileCommon extends InstancedBlockTile +{ + def getEnergy:Double + def setEnergy(en:Double) + + def maxEnergy:Double + + abstract override def load(tag:NBTTagCompound) + { + super.load(tag) + setEnergy(tag.getDouble("energy")) + } + + abstract override def save(tag:NBTTagCompound) + { + super.save(tag) + tag.setDouble("energy", getEnergy) + } +} + +trait TInfinitePower extends TPowerTileCommon +{ + override def getEnergy = Double.MaxValue + override def setEnergy(en:Double){} + + override def maxEnergy = Double.MaxValue +} + +trait TPowerTile extends TPowerTileCommon with TInfinitePower//TODO mixin with all implementors of TPowerTile \ No newline at end of file diff --git a/src/mrtjp/relocation/proxies.scala b/src/mrtjp/relocation/proxies.scala new file mode 100644 index 0000000..283d1fe --- /dev/null +++ b/src/mrtjp/relocation/proxies.scala @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation + +import cpw.mods.fml.common.FMLCommonHandler +import cpw.mods.fml.relauncher.{Side, SideOnly} +import mrtjp.core.block.TileRenderRegistry +import mrtjp.relocation.api.RelocationAPI.{instance => API} +import net.minecraftforge.common.MinecraftForge + +class RelocationProxy_server +{ + def preinit() + { + RelocationMod.blockMotor = new BlockMotor + RelocationMod.blockFrame = new BlockFrame + RelocationMod.blockMovingRow = new BlockMovingRow + + API.registerTileMover("saveload", + "Saves the tile and then reloads it in the next position. Reliable but CPU intensive.", + new SaveLoadTileHandler) + + API.registerTileMover("coordpush", + "Physically changes the location of tiles. Works if tiles do not cache their position.", + new CoordPushTileHandler) + + API.registerTileMover("static", "Setting this disables movement for the specified block.", new StaticTileHandler) + + API.registerPreferredMover("default", "saveload") + API.registerPreferredMover("mod:minecraft", "coordpush") + API.registerPreferredMover("mod:Relocation", "coordpush") + API.registerPreferredMover("mod:ComputerCraft", "coordpush") + API.registerPreferredMover("mod:EnderStorage", "coordpush") + API.registerPreferredMover("mod:ChickenChunks", "coordpush") + API.registerPreferredMover("mod:Translocator", "coordpush") + } + + def init() + { + RelocationConfig.loadConfig() + } + + def postinit(){} +} + +class RelocationProxy_client extends RelocationProxy_server +{ + @SideOnly(Side.CLIENT) + override def preinit() + { + super.preinit() + FMLCommonHandler.instance.bus.register(RenderTicker) + MinecraftForge.EVENT_BUS.register(MovingRenderer) + + TileRenderRegistry.setRenderer(RelocationMod.blockMotor, 0, MotorRenderer) + TileRenderRegistry.setRenderer(RelocationMod.blockFrame, 0, FrameRenderer) + } + + @SideOnly(Side.CLIENT) + override def postinit() + { + super.postinit() + } +} + +object RelocationProxy extends RelocationProxy_client \ No newline at end of file diff --git a/src/mrtjp/relocation/registry.scala b/src/mrtjp/relocation/registry.scala new file mode 100644 index 0000000..3121c08 --- /dev/null +++ b/src/mrtjp/relocation/registry.scala @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation + +import java.security.InvalidKeyException + +import codechicken.lib.vec.BlockCoord +import cpw.mods.fml.common.Loader +import gnu.trove.impl.sync.{TSynchronizedIntObjectMap, TSynchronizedLongObjectMap, TSynchronizedLongSet} +import gnu.trove.map.hash.{TIntObjectHashMap, TLongObjectHashMap} +import gnu.trove.set.hash.TLongHashSet +import mrtjp.core.block.BlockLib +import mrtjp.core.world.WorldLib._ +import mrtjp.relocation.api.{IFrame, IFrameInteraction, ITileMover} +import net.minecraft.block.Block +import net.minecraft.init.Blocks +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.tileentity.TileEntity +import net.minecraft.world.World + +import scala.collection.immutable.ListMap + +object MovingTileRegistry extends ITileMover +{ + val rKeyVal = raw"([\w:]+)\s*->\s*(.+)".r + val rName = raw"(.+)".r + val rNameMetaM = raw"(.+)m(\d+)".r + val rMod = raw"mod:(\w+)".r + + var latchMap = Map[(Block, Int), Set[(Block, Int)]]().withDefaultValue(Set()) + var interactionList = Seq[IFrameInteraction]() + + var blockMetaMap = Map[(Block, Int), ITileMover]() + var modMap = Map[String, ITileMover]() + + var moverDescMap = Map[String, String]() + var moverNameMap = Map[String, ITileMover]() + + var defaultMover:ITileMover = _ + var preferredMovers = Seq[(String, String)]() + var mandatoryMovers = Seq[(String, String)]() + + def parseKV(kv:Seq[String]) = kv.map { case rKeyVal(k, v) => (k, v); case s => throw new MatchError(s"Illegal [k -> v] pair: $s") } + def parseBlockMeta(b:String) = b match + { + case rNameMetaM(name, meta) => Block.getBlockFromName(fixName(name)) -> meta.toInt + case rName(name) => Block.getBlockFromName(fixName(name)) -> -1 + case _ => throw new MatchError(s"Illegal set part: $b") + } + def fixName(name:String) = name.indexOf(':') match + { + case -1 => "minecraft:"+name + case i => name + } + + def parseAndAddLatchSets(kv:Seq[String]) + { + parseKV(kv).foreach(b => addLatchSet(parseBlockMeta(b._1), parseBlockMeta(b._2))) + } + + def parseAndSetMovers(kv:Seq[String]) = + { + var moverMap = ListMap(parseKV(kv):_*) + for ((k, v) <- preferredMovers) if (!moverMap.contains(k)) moverMap += k -> v + for (pair <- mandatoryMovers) moverMap += pair + moverMap.foreach(h => setMover(h._1, h._2)) + moverMap.map(p => p._1+" -> "+p._2).toArray + } + + def addLatchSet(b1:(Block, Int), b2:(Block, Int)) + { + latchMap += b1 -> (latchMap(b1)+b2) + } + + def setMover(that:String, m:String) + { + val h = moverNameMap.getOrElse(m, throw new InvalidKeyException("[ForgeRelocation] No tile mover named '"+m+"'")) + that match + { + case "default" => defaultMover = h + case rMod(mod) if Loader.isModLoaded(mod) => modMap += mod -> h + case _ => blockMetaMap += parseBlockMeta(that) -> h + } + } + + def registerTileMover(name:String, desc:String, m:ITileMover) + { + moverDescMap += name -> desc + moverNameMap += name -> m + } + + private def getHandler(b:Block, m:Int) = + { + blockMetaMap.getOrElse((b, m), blockMetaMap.getOrElse((b, -1), + modMap.getOrElse(BlockLib.getModId(b), defaultMover))) + } + + override def canMove(w:World, x:Int, y:Int, z:Int) = + { + val meta = w.getBlockMetadata(x, y, z) + w.getBlock(x, y, z) match + { + case block:Block => getHandler(block, meta).canMove(w, x, y, z) + case _ => false + } + } + + override def move(w:World, x:Int, y:Int, z:Int, side:Int) + { + val meta = w.getBlockMetadata(x, y, z) + w.getBlock(x, y, z) match + { + case block:Block => getHandler(block, meta).move(w, x, y, z, side) + case _ => + } + } + + override def postMove(w:World, x:Int, y:Int, z:Int) + { + val meta = w.getBlockMetadata(x, y, z) + w.getBlock(x, y, z) match + { + case block:Block => getHandler(block, meta).postMove(w, x, y, z) + case _ => + } + } + + def resolveStick(w:World, pos:BlockCoord, side:Int):Boolean = + { + val block = getBlock(w, pos) + if (block.isInstanceOf[IFrame] && block.asInstanceOf[IFrame]. + latchSide(w, pos.x, pos.y, pos.z, side)) return true + + val te = getTileEntity(w, pos) + if (te.isInstanceOf[IFrame] && te.asInstanceOf[IFrame]. + latchSide(w, pos.x, pos.y, pos.z, side)) return true + + if (latchInteraction(w, pos.x, pos.y, pos.z, side)) return true + + if (latchSet(w, pos.x, pos.y, pos.z, side)) return true + + false + } + + def latchSet(w:World, x:Int, y:Int, z:Int, side:Int) = + { + val pos = new BlockCoord(x, y, z).offset(side) + val b1 = getBlockMetaPair(w, x, y, z) + val b2 = getBlockMetaPair(w, pos.x, pos.y, pos.z) + + val set = latchMap.getOrElse(b1, latchMap((b1._1, -1))) + set.contains(b2) || set.contains((b2._1, -1)) + } + + def latchInteraction(w:World, x:Int, y:Int, z:Int, side:Int) = interactionList.find(_.canInteract(w, x, y, z)) match + { + case Some(i) => i.latchSide(w, x, y, z, side) + case None => false + } +} + +object MovementManager +{ + val eps = 1.0/0x10000 + + val clientMap = new TSynchronizedLongObjectMap(new TLongObjectHashMap[RenderPos]) + val serverMap = new TSynchronizedIntObjectMap(new TIntObjectHashMap[TSynchronizedLongSet]) + + def isMoving(w:World, bc:BlockCoord):Boolean = + isMoving(w, bc.x, bc.y, bc.z) + + def isMoving(w:World, x:Int, y:Int, z:Int):Boolean = + { + if (w.isRemote) clientMap.containsKey(packCoords(x, y, z)) + else + { + val dim = w.provider.dimensionId + if (serverMap.containsKey(dim)) + { + val worldSet = serverMap.get(dim) + worldSet.contains(packCoords(x, y, z)) + } + else false + } + } + + def getData(w:World, bc:BlockCoord):RenderPos = + getData(w, bc.x, bc.y, bc.z) + + def getData(w:World, x:Int, y:Int, z:Int):RenderPos = + { + if (w.isRemote) clientMap.get(packCoords(x, y, z)) + else null + } + + def addMoving(w:World, bc:BlockCoord, offset:RenderPos) = this.synchronized + { + if (w.isRemote) + { + clientMap.put(packCoords(bc.x, bc.y, bc.z), offset) + w.func_147451_t(bc.x, bc.y, bc.z) + for (s <- 0 until 6) + { + val pos = bc.copy.offset(s) + w.func_147479_m(pos.x, pos.y, pos.z) + } + } + else + { + val dim = w.provider.dimensionId + if (!serverMap.containsKey(dim)) + serverMap.put(dim, new TSynchronizedLongSet(new TLongHashSet)) + + val worldSet = serverMap.get(dim) + worldSet.add(packCoords(bc.x, bc.y, bc.z)) + } + } + + def removeMoving(w:World, bc:BlockCoord) = this.synchronized + { + if (w.isRemote) + { + clientMap.remove(packCoords(bc.x, bc.y, bc.z)) + w.func_147451_t(bc.x, bc.y, bc.z) + for (s <- 0 until 6) + { + val pos = bc.copy.offset(s) + w.func_147479_m(pos.x, pos.y, pos.z) + } + } + else + { + val dim = w.provider.dimensionId + if (serverMap.containsKey(dim)) + { + val worldSet = serverMap.get(dim) + worldSet.remove(packCoords(bc.x, bc.y, bc.z)) + } + } + } +} + +class CoordPushTileHandler extends ITileMover +{ + override def canMove(w:World, x:Int, y:Int, z:Int) = true + + override def move(w:World, x:Int, y:Int, z:Int, side:Int) + { + val (b, meta, te) = getBlockInfo(w, x, y, z) + val pos = new BlockCoord(x, y, z).offset(side) + if (te != null) + { + te.invalidate() + uncheckedRemoveTileEntity(w, x, y, z) + } + uncheckedSetBlock(w, x, y, z, Blocks.air, 0) + uncheckedSetBlock(w, pos.x, pos.y, pos.z, b, meta) + if (te != null) + { + te.xCoord = pos.x + te.yCoord = pos.y + te.zCoord = pos.z + te.validate() + uncheckedSetTileEntity(w, pos.x, pos.y, pos.z, te) + } + } + + override def postMove(w:World, x:Int, y:Int, z:Int){} +} + +class SaveLoadTileHandler extends ITileMover +{ + override def canMove(w:World, x:Int, y:Int, z:Int) = true + + override def move(w:World, x:Int, y:Int, z:Int, side:Int) + { + val (b, meta, te) = getBlockInfo(w, x, y, z) + val pos = new BlockCoord(x, y, z).offset(side) + val tag = if (te != null) + { + val tag = new NBTTagCompound + te.writeToNBT(tag) + tag.setInteger("x", pos.x) + tag.setInteger("y", pos.y) + tag.setInteger("z", pos.z) + te.onChunkUnload() + w.removeTileEntity(x, y, z) + tag + } + else null + uncheckedSetBlock(w, x, y, z, Blocks.air, 0) + uncheckedSetBlock(w, pos.x, pos.y, pos.z, b, meta) + if (tag != null) + { + TileEntity.createAndLoadEntity(tag) match + { + case te:TileEntity => + w.getChunkFromBlockCoords(pos.x, pos.z).addTileEntity(te) + case _ => + } + } + } + + override def postMove(w:World, x:Int, y:Int, z:Int){} +} + +class StaticTileHandler extends ITileMover +{ + override def canMove(w:World, x:Int, y:Int, z:Int) = false + + override def move(w:World, x:Int, y:Int, z:Int, side:Int){} + + override def postMove(w:World, x:Int, y:Int, z:Int){} +} \ No newline at end of file diff --git a/src/mrtjp/relocation/renders.scala b/src/mrtjp/relocation/renders.scala new file mode 100644 index 0000000..44cc5ce --- /dev/null +++ b/src/mrtjp/relocation/renders.scala @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation + +import codechicken.lib.lighting.LightModel +import codechicken.lib.render.CCModel._ +import codechicken.lib.render._ +import codechicken.lib.render.uv.{IconTransformation, MultiIconTransformation, UVTransformation} +import codechicken.lib.vec._ +import mrtjp.core.block.TInstancedBlockRender +import mrtjp.core.vec.InvertX +import mrtjp.core.world.WorldLib +import net.minecraft.client.renderer.RenderBlocks +import net.minecraft.client.renderer.texture.IIconRegister +import net.minecraft.util.IIcon +import net.minecraft.world.IBlockAccess + +//TODO use cube map renderer +object MotorRenderer extends TInstancedBlockRender +{ + var bottom:IIcon = _ + var side:IIcon = _ + var sidew:IIcon = _ + var sidee:IIcon = _ + var top:IIcon = _ + var iconT:UVTransformation = _ + + val models = Array.ofDim[CCModel](6, 4) + + { + val base = CCModel.quadModel(24).generateBlock(0, Cuboid6.full) + for (s <- 0 until 6) for (r <- 0 until 4) + { + val m = base.copy.apply(Rotation.sideOrientation(s, r).at(Vector3.center)) + m.computeNormals() + m.computeLighting(LightModel.standardLightModel) + models(s)(r) = m + } + } + + override def renderWorldBlock(r:RenderBlocks, w:IBlockAccess, x:Int, y:Int, z:Int, meta:Int) + { + val te = WorldLib.getTileEntity(w, x, y, z, classOf[TileMotor]) + if (te != null) + { + TextureUtils.bindAtlas(0) + CCRenderState.reset() + CCRenderState.lightMatrix.locate(w, x, y, z) + CCRenderState.setBrightness(w, x, y, z) + models(te.side)(te.rotation).render(new Translation(x, y, z), iconT) + } + } + + override def getIcon(s:Int, meta:Int) = s match + { + case 0 => bottom + case 1 => top + case 2 => side + case 3 => side + case 4 => sidew + case 5 => sidee + } + + private val invTranslation = new Translation(0, -0.075, 0) + override def renderInvBlock(r:RenderBlocks, meta:Int) + { + TextureUtils.bindAtlas(0) + CCRenderState.reset() + CCRenderState.setDynamic() + CCRenderState.pullLightmap() + CCRenderState.setPipeline(iconT, invTranslation) + CCRenderState.startDrawing() + BlockRenderer.renderCuboid(Cuboid6.full, 0) + CCRenderState.draw() + } + + override def registerIcons(reg:IIconRegister) + { + bottom = reg.registerIcon("relocation:motor/bottom") + top = reg.registerIcon("relocation:motor/top") + side = reg.registerIcon("relocation:motor/side") + sidew = reg.registerIcon("relocation:motor/sidew") + sidee = reg.registerIcon("relocation:motor/sidee") + + iconT = new MultiIconTransformation(bottom, top, side, side, sidew, sidee) + } +} + +object FrameRenderer extends TInstancedBlockRender +{ + var icon:IIcon = _ + var iconT:UVTransformation = _ + + override def renderWorldBlock(r:RenderBlocks, w:IBlockAccess, x:Int, y:Int, z:Int, meta:Int) + { + TextureUtils.bindAtlas(0) + CCRenderState.reset() + CCRenderState.lightMatrix.locate(w, x, y, z) + CCRenderState.setBrightness(w, x, y, z) + RenderFrame.render(new Vector3(x, y, z)) + } + + override def getIcon(side:Int, meta:Int) = icon + + private val invVec = new Vector3(0, -0.075, 0) + override def renderInvBlock(r:RenderBlocks, meta:Int) + { + TextureUtils.bindAtlas(0) + CCRenderState.reset() + CCRenderState.setDynamic() + CCRenderState.pullLightmap() + + CCRenderState.startDrawing() + RenderFrame.render(invVec) + + CCRenderState.render() + CCRenderState.draw() + } + + override def registerIcons(reg:IIconRegister) + { + icon = reg.registerIcon("relocation:frame") + iconT = new IconTransformation(icon) + } +} + +object RenderFrame +{ + val model = parseModel("frame") + val model_simple = parseModel("frame_simple") + + def getFrameForRender = if (RelocationConfig.simpleModel) model_simple else model + + private def parseModel(name:String) = + { + val m = combine(parseObjModels(this.getClass.getResource( + "/assets/relocation/textures/obj/"+name+".obj").openStream(), + 7, InvertX).values()) + + m.shrinkUVs(0.0005) + m.apply(new Scale(1.00075, 1.00075, 1.00075)) + m.apply(new Translation(Vector3.center)) + m.computeNormals + m.computeLighting(LightModel.standardLightModel) + m + } + + def render(pos:Vector3) + { + getFrameForRender.render(new Translation(pos), FrameRenderer.iconT) + } +} \ No newline at end of file diff --git a/src/mrtjp/relocation/util.scala b/src/mrtjp/relocation/util.scala new file mode 100644 index 0000000..143c39d --- /dev/null +++ b/src/mrtjp/relocation/util.scala @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014. + * Created by MrTJP. + * All rights reserved. + */ +package mrtjp.relocation + +import java.util.{ArrayList => JAList, List => JList, Set => JSet, TreeSet => JTreeSet} + +import codechicken.lib.vec.BlockCoord +import cpw.mods.fml.common.ObfuscationReflectionHelper +import mrtjp.core.vec.ModelRayTracer +import net.minecraft.client.Minecraft +import net.minecraft.tileentity.TileEntity +import net.minecraft.util.Vec3 +import net.minecraft.world._ + +import scala.collection.JavaConversions._ +import scala.collection.immutable.HashSet + +object Utils +{ + def raytraceFrame(x:Double, y:Double, z:Double, start:Vec3, end:Vec3) = + ModelRayTracer.raytraceModel(x, y, z, start, end, RenderFrame.getFrameForRender) + + def rescheduleTicks(world:World, blocks:Set[BlockCoord], allBlocks:Set[BlockCoord], dir:Int) = world match + { + case world:WorldServer => + val hash = ObfuscationReflectionHelper.getPrivateValue(classOf[WorldServer], world, "field_73064_N", + "pendingTickListEntriesHashSet").asInstanceOf[JSet[NextTickListEntry]] + + val tree = ObfuscationReflectionHelper.getPrivateValue(classOf[WorldServer], world, "field_73065_O", + "pendingTickListEntriesTreeSet").asInstanceOf[JTreeSet[NextTickListEntry]] + + val list = ObfuscationReflectionHelper.getPrivateValue(classOf[WorldServer], world, "field_94579_S", + "pendingTickListEntriesThisTick").asInstanceOf[JAList[NextTickListEntry]] + + val isOptifine = world.getClass.getName == "WorldServerOF" + + val chunks = allBlocks.map(b => world.getChunkFromBlockCoords(b.x, b.z)).filter(_ != null) + + val scheduledTicks = chunks.flatMap(ch => world.getPendingBlockUpdates(ch, !isOptifine) + .asInstanceOf[JAList[NextTickListEntry]] match + { + case null => HashSet[NextTickListEntry]() + case tList => tList.toSet + }) + + if (isOptifine) for (tick <- scheduledTicks) + { + tree.remove(tick) + hash.remove(tick) + list.remove(tick) + } + + for (tick <- scheduledTicks) + { + val bc = new BlockCoord(tick.xCoord, tick.yCoord, tick.zCoord) + if (blocks(bc)) + { + bc.offset(dir) + tick.xCoord = bc.x + tick.yCoord = bc.y + tick.zCoord = bc.z + } + } + + for (tick <- scheduledTicks) if (!hash.contains(tick)) + { + hash.add(tick) + tree.add(tick) + } + case _ => + } + + def rerenderBlocks(world:World, blocks:Set[BlockCoord]) + { + if (world.isRemote) + { + val mc = Minecraft.getMinecraft + val teList = mc.renderGlobal.tileEntities.asInstanceOf[JList[TileEntity]] + + for (pass <- 0 to 1) + { + for(c <- blocks; te = world.getTileEntity(c.x, c.y, c.z)) + { + if (te != null) pass match + { + case 0 => teList.remove(te) + case 1 => teList.add(te) + } + mc.renderGlobal.markBlockForRenderUpdate(c.x, c.y, c.z) + } + mc.renderGlobal.updateRenderers(mc.renderViewEntity, false) + } + } + } +} \ No newline at end of file