diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..835e8dc --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.gradle +.idea +build \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..86676ec --- /dev/null +++ b/LICENSE @@ -0,0 +1,26 @@ +BSD 2-Clause License + +Copyright (c) 2016-2017, Adam +Copyright (c) 2020, Null +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..017efc4 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# cache +Tools for modifying the osrs cache diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..07d09f4 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019 Owain van Brakel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.apache.tools.ant.filters.ReplaceTokens + +plugins { + java + `maven-publish` +} + +group = "com.openosrs" +version = "1.0-SNAPSHOT" + +repositories { + jcenter() + mavenCentral() + mavenLocal() +} + +dependencies { + annotationProcessor("org.projectlombok:lombok:1.18.10") + implementation("org.projectlombok:lombok:1.18.10") + + implementation("com.google.code.gson:gson:2.8.6") + implementation("com.google.guava:guava:28.2-jre") + implementation("commons-cli:commons-cli:1.4") + implementation("io.netty:netty-buffer:4.1.44.Final") + implementation("org.antlr:antlr4-runtime:4.7.2") + implementation("org.apache.commons:commons-compress:1.19") + implementation("org.slf4j:slf4j-api:1.7.30") +} + +configure { + sourceCompatibility = JavaVersion.VERSION_11 +} + +tasks { + compileJava { + options.encoding = "UTF-8" + } +} + +val sourcesJar by tasks.registering(Jar::class) { + classifier = "sources" + from(sourceSets.main.get().allSource) +} + +publishing { + repositories { + maven { + url = uri("$buildDir/repo") + } + } + publications { + register("mavenJava", MavenPublication::class) { + from(components["java"]) + artifact(sourcesJar.get()) + } + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..87b738c 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 100644 index 0000000..1ba7206 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..af6708f --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m"' + +# 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 +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +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" -a "$nonstop" = "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"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + 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 + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..6d57edc --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@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 + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" + +@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 Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_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=%* + +: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/osrs_cache/main_file_cache.dat2 b/osrs_cache/main_file_cache.dat2 new file mode 100644 index 0000000..09cb729 Binary files /dev/null and b/osrs_cache/main_file_cache.dat2 differ diff --git a/osrs_cache/main_file_cache.idx0 b/osrs_cache/main_file_cache.idx0 new file mode 100644 index 0000000..6f3a837 Binary files /dev/null and b/osrs_cache/main_file_cache.idx0 differ diff --git a/osrs_cache/main_file_cache.idx1 b/osrs_cache/main_file_cache.idx1 new file mode 100644 index 0000000..aff4296 Binary files /dev/null and b/osrs_cache/main_file_cache.idx1 differ diff --git a/osrs_cache/main_file_cache.idx10 b/osrs_cache/main_file_cache.idx10 new file mode 100644 index 0000000..512a7aa Binary files /dev/null and b/osrs_cache/main_file_cache.idx10 differ diff --git a/osrs_cache/main_file_cache.idx11 b/osrs_cache/main_file_cache.idx11 new file mode 100644 index 0000000..43e0aef Binary files /dev/null and b/osrs_cache/main_file_cache.idx11 differ diff --git a/osrs_cache/main_file_cache.idx12 b/osrs_cache/main_file_cache.idx12 new file mode 100644 index 0000000..9e9228f Binary files /dev/null and b/osrs_cache/main_file_cache.idx12 differ diff --git a/osrs_cache/main_file_cache.idx13 b/osrs_cache/main_file_cache.idx13 new file mode 100644 index 0000000..be71ea6 Binary files /dev/null and b/osrs_cache/main_file_cache.idx13 differ diff --git a/osrs_cache/main_file_cache.idx14 b/osrs_cache/main_file_cache.idx14 new file mode 100644 index 0000000..459bcc1 Binary files /dev/null and b/osrs_cache/main_file_cache.idx14 differ diff --git a/osrs_cache/main_file_cache.idx15 b/osrs_cache/main_file_cache.idx15 new file mode 100644 index 0000000..4a43374 Binary files /dev/null and b/osrs_cache/main_file_cache.idx15 differ diff --git a/osrs_cache/main_file_cache.idx16 b/osrs_cache/main_file_cache.idx16 new file mode 100644 index 0000000..cae4a1e Binary files /dev/null and b/osrs_cache/main_file_cache.idx16 differ diff --git a/osrs_cache/main_file_cache.idx17 b/osrs_cache/main_file_cache.idx17 new file mode 100644 index 0000000..fa96494 Binary files /dev/null and b/osrs_cache/main_file_cache.idx17 differ diff --git a/osrs_cache/main_file_cache.idx18 b/osrs_cache/main_file_cache.idx18 new file mode 100644 index 0000000..be8ce87 Binary files /dev/null and b/osrs_cache/main_file_cache.idx18 differ diff --git a/osrs_cache/main_file_cache.idx19 b/osrs_cache/main_file_cache.idx19 new file mode 100644 index 0000000..3c9209f Binary files /dev/null and b/osrs_cache/main_file_cache.idx19 differ diff --git a/osrs_cache/main_file_cache.idx2 b/osrs_cache/main_file_cache.idx2 new file mode 100644 index 0000000..eb6e59a Binary files /dev/null and b/osrs_cache/main_file_cache.idx2 differ diff --git a/osrs_cache/main_file_cache.idx20 b/osrs_cache/main_file_cache.idx20 new file mode 100644 index 0000000..515d40f Binary files /dev/null and b/osrs_cache/main_file_cache.idx20 differ diff --git a/osrs_cache/main_file_cache.idx255 b/osrs_cache/main_file_cache.idx255 new file mode 100644 index 0000000..2579ae1 Binary files /dev/null and b/osrs_cache/main_file_cache.idx255 differ diff --git a/osrs_cache/main_file_cache.idx3 b/osrs_cache/main_file_cache.idx3 new file mode 100644 index 0000000..1f0fa43 Binary files /dev/null and b/osrs_cache/main_file_cache.idx3 differ diff --git a/osrs_cache/main_file_cache.idx4 b/osrs_cache/main_file_cache.idx4 new file mode 100644 index 0000000..3ec6f1b Binary files /dev/null and b/osrs_cache/main_file_cache.idx4 differ diff --git a/osrs_cache/main_file_cache.idx5 b/osrs_cache/main_file_cache.idx5 new file mode 100644 index 0000000..f5dda40 Binary files /dev/null and b/osrs_cache/main_file_cache.idx5 differ diff --git a/osrs_cache/main_file_cache.idx6 b/osrs_cache/main_file_cache.idx6 new file mode 100644 index 0000000..b7121a5 Binary files /dev/null and b/osrs_cache/main_file_cache.idx6 differ diff --git a/osrs_cache/main_file_cache.idx7 b/osrs_cache/main_file_cache.idx7 new file mode 100644 index 0000000..c44214d Binary files /dev/null and b/osrs_cache/main_file_cache.idx7 differ diff --git a/osrs_cache/main_file_cache.idx8 b/osrs_cache/main_file_cache.idx8 new file mode 100644 index 0000000..e847a08 Binary files /dev/null and b/osrs_cache/main_file_cache.idx8 differ diff --git a/osrs_cache/main_file_cache.idx9 b/osrs_cache/main_file_cache.idx9 new file mode 100644 index 0000000..a8571ab Binary files /dev/null and b/osrs_cache/main_file_cache.idx9 differ diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..e5bf618 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,2 @@ +rootProject.name = "cache" + diff --git a/src/main/antlr4/net/runelite/cache/script/assembler/rs2asm.g4 b/src/main/antlr4/net/runelite/cache/script/assembler/rs2asm.g4 new file mode 100644 index 0000000..f8b33e8 --- /dev/null +++ b/src/main/antlr4/net/runelite/cache/script/assembler/rs2asm.g4 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +grammar rs2asm; + +prog: NEWLINE* (header NEWLINE+)* (line NEWLINE+)+ ; + +header: id | int_stack_count | string_stack_count | int_var_count | string_var_count ; + +id: '.id ' id_value ; +int_stack_count: '.int_stack_count ' int_stack_value ; +string_stack_count: '.string_stack_count ' string_stack_value ; +int_var_count: '.int_var_count ' int_var_value ; +string_var_count: '.string_var_count ' string_var_value ; + +id_value: INT ; +int_stack_value: INT ; +string_stack_value: INT ; +int_var_value: INT ; +string_var_value: INT ; + +line: instruction | label | switch_lookup ; +instruction: instruction_name instruction_operand ; +label: IDENTIFIER ':' ; + +instruction_name: name_string | name_opcode ; +name_string: IDENTIFIER ; +name_opcode: INT ; + +instruction_operand: operand_int | operand_qstring | operand_label | ; +operand_int: INT ; +operand_qstring: QSTRING ; +operand_label: IDENTIFIER ; + +switch_lookup: switch_key ':' switch_value ; +switch_key: INT ; +switch_value: IDENTIFIER ; + +NEWLINE: ( '\r' | '\n' )+ ; +INT: '-'? [0-9]+ ; +QSTRING: '"' (~('"' | '\\' | '\r' | '\n') | '\\' ('"' | '\\'))* '"' ; +IDENTIFIER: [a-zA-Z0-9_]+ ; +COMMENT: ';' ~( '\r' | '\n' )* -> channel(HIDDEN) ; + +WS: (' ' | '\t')+ -> channel(HIDDEN) ; \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/AreaManager.java b/src/main/java/net/runelite/cache/AreaManager.java new file mode 100644 index 0000000..96967b8 --- /dev/null +++ b/src/main/java/net/runelite/cache/AreaManager.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.AreaDefinition; +import net.runelite.cache.definitions.loaders.AreaLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; + +public class AreaManager +{ + private final Store store; + private final Map areas = new HashMap<>(); + + public AreaManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.AREA.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile file : files.getFiles()) + { + AreaLoader loader = new AreaLoader(); + AreaDefinition area = loader.load(file.getContents(), file.getFileId()); + areas.put(area.id, area); + } + } + + public Collection getAreas() + { + return Collections.unmodifiableCollection(areas.values()); + } + + public AreaDefinition getArea(int areaId) + { + return areas.get(areaId); + } +} diff --git a/src/main/java/net/runelite/cache/Cache.java b/src/main/java/net/runelite/cache/Cache.java new file mode 100644 index 0000000..bfaf424 --- /dev/null +++ b/src/main/java/net/runelite/cache/Cache.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.io.File; +import java.io.IOException; +import net.runelite.cache.fs.Store; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; + +public class Cache +{ + public static void main(String[] args) throws IOException + { + Options options = new Options(); + + options.addOption("c", "cache", true, "cache base"); + + options.addOption(null, "items", true, "directory to dump items to"); + options.addOption(null, "npcs", true, "directory to dump npcs to"); + options.addOption(null, "objects", true, "directory to dump objects to"); + options.addOption(null, "sprites", true, "directory to dump sprites to"); + + CommandLineParser parser = new DefaultParser(); + CommandLine cmd; + try + { + cmd = parser.parse(options, args); + } + catch (ParseException ex) + { + System.err.println("Error parsing command line options: " + ex.getMessage()); + System.exit(-1); + return; + } + + String cache = cmd.getOptionValue("cache"); + + Store store = loadStore(cache); + + if (cmd.hasOption("items")) + { + String itemdir = cmd.getOptionValue("items"); + + if (itemdir == null) + { + System.err.println("Item directory must be specified"); + return; + } + + System.out.println("Dumping items to " + itemdir); + dumpItems(store, new File(itemdir)); + } + else if (cmd.hasOption("npcs")) + { + String npcdir = cmd.getOptionValue("npcs"); + + if (npcdir == null) + { + System.err.println("NPC directory must be specified"); + return; + } + + System.out.println("Dumping npcs to " + npcdir); + dumpNpcs(store, new File(npcdir)); + } + else if (cmd.hasOption("objects")) + { + String objectdir = cmd.getOptionValue("objects"); + + if (objectdir == null) + { + System.err.println("Object directory must be specified"); + return; + } + + System.out.println("Dumping objects to " + objectdir); + dumpObjects(store, new File(objectdir)); + } + else if (cmd.hasOption("sprites")) + { + String spritedir = cmd.getOptionValue("sprites"); + + if (spritedir == null) + { + System.err.println("Sprite directory must be specified"); + return; + } + + System.out.println("Dumping sprites to " + spritedir); + dumpSprites(store, new File(spritedir)); + } + else + { + System.err.println("Nothing to do"); + } + } + + private static Store loadStore(String cache) throws IOException + { + Store store = new Store(new File("./osrs_cache/")); + store.load(); + return store; + } + + private static void dumpItems(Store store, File itemdir) throws IOException + { + ItemManager dumper = new ItemManager(store); + dumper.load(); + dumper.export(itemdir); + dumper.java(itemdir); + } + + private static void dumpNpcs(Store store, File npcdir) throws IOException + { + NpcManager dumper = new NpcManager(store); + dumper.load(); + dumper.dump(npcdir); + dumper.java(npcdir); + } + + private static void dumpObjects(Store store, File objectdir) throws IOException + { + ObjectManager dumper = new ObjectManager(store); + dumper.load(); + dumper.dump(objectdir); + dumper.java(objectdir); + } + + private static void dumpSprites(Store store, File spritedir) throws IOException + { + SpriteManager dumper = new SpriteManager(store); + dumper.load(); + dumper.export(spritedir); + } +} diff --git a/src/main/java/net/runelite/cache/ConfigType.java b/src/main/java/net/runelite/cache/ConfigType.java new file mode 100644 index 0000000..13056e2 --- /dev/null +++ b/src/main/java/net/runelite/cache/ConfigType.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache; + +public enum ConfigType +{ + // types from https://github.com/im-frizzy/OpenRS/blob/master/source/net/openrs/cache/type/ConfigArchive.java + UNDERLAY(1), + IDENTKIT(3), + OVERLAY(4), + INV(5), + OBJECT(6), + ENUM(8), + NPC(9), + ITEM(10), + PARAMS(11), + SEQUENCE(12), + SPOTANIM(13), + VARBIT(14), + VARCLIENT(19), + VARCLIENTSTRING(15), + VARPLAYER(16), + STRUCT(34), + AREA(35); + + private final int id; + + ConfigType(int id) + { + this.id = id; + } + + public int getId() + { + return id; + } +} diff --git a/src/main/java/net/runelite/cache/HeightMapDumper.java b/src/main/java/net/runelite/cache/HeightMapDumper.java new file mode 100644 index 0000000..5db3081 --- /dev/null +++ b/src/main/java/net/runelite/cache/HeightMapDumper.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.IOException; +import net.runelite.cache.fs.Store; +import net.runelite.cache.region.Region; +import net.runelite.cache.region.RegionLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HeightMapDumper +{ + private static final Logger logger = LoggerFactory.getLogger(HeightMapDumper.class); + + private static final int MAP_SCALE = 1; + private static final float MAX_HEIGHT = 2048f; + + private final Store store; + private RegionLoader regionLoader; + + public HeightMapDumper(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + regionLoader = new RegionLoader(store); + regionLoader.loadRegions(); + regionLoader.calculateBounds(); + } + + public BufferedImage drawHeightMap(int z) + { + int minX = regionLoader.getLowestX().getBaseX(); + int minY = regionLoader.getLowestY().getBaseY(); + + int maxX = regionLoader.getHighestX().getBaseX() + Region.X; + int maxY = regionLoader.getHighestY().getBaseY() + Region.Y; + + int dimX = maxX - minX; + int dimY = maxY - minY; + + dimX *= MAP_SCALE; + dimY *= MAP_SCALE; + + logger.info("Map image dimensions: {}px x {}px, {}px per map square ({} MB)", dimX, dimY, MAP_SCALE, (dimX * dimY / 1024 / 1024)); + + BufferedImage image = new BufferedImage(dimX, dimY, BufferedImage.TYPE_INT_RGB); + draw(image, z); + return image; + } + + private void draw(BufferedImage image, int z) + { + int max = Integer.MIN_VALUE; + int min = Integer.MAX_VALUE; + + for (Region region : regionLoader.getRegions()) + { + int baseX = region.getBaseX(); + int baseY = region.getBaseY(); + + // to pixel X + int drawBaseX = baseX - regionLoader.getLowestX().getBaseX(); + + // to pixel Y. top most y is 0, but the top most + // region has the greatest y, so invert + int drawBaseY = regionLoader.getHighestY().getBaseY() - baseY; + + for (int x = 0; x < Region.X; ++x) + { + int drawX = drawBaseX + x; + + for (int y = 0; y < Region.Y; ++y) + { + int drawY = drawBaseY + (Region.Y - 1 - y); + + int height = region.getTileHeight(z, x, y); + if (height > max) + { + max = height; + } + if (height < min) + { + min = height; + } + + int rgb = toColor(height); + + drawMapSquare(image, drawX, drawY, rgb); + } + } + } + System.out.println("max " + max); + System.out.println("min " + min); + } + + private int toColor(int height) + { + // height seems to be between -2040 and 0, inclusive + height = -height; + // Convert to between 0 and 1 + float color = (float) height / MAX_HEIGHT; + + assert color >= 0.0f && color <= 1.0f; + + return new Color(color, color, color).getRGB(); + } + + private void drawMapSquare(BufferedImage image, int x, int y, int rgb) + { + x *= MAP_SCALE; + y *= MAP_SCALE; + + for (int i = 0; i < MAP_SCALE; ++i) + { + for (int j = 0; j < MAP_SCALE; ++j) + { + image.setRGB(x + i, y + j, rgb); + } + } + } +} diff --git a/src/main/java/net/runelite/cache/IndexType.java b/src/main/java/net/runelite/cache/IndexType.java new file mode 100644 index 0000000..813594b --- /dev/null +++ b/src/main/java/net/runelite/cache/IndexType.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache; + +public enum IndexType +{ + FRAMES(0), + FRAMEMAPS(1), + CONFIGS(2), + INTERFACES(3), + SOUNDEFFECTS(4), + MAPS(5), + TRACK1(6), + MODELS(7), + SPRITES(8), + TEXTURES(9), + BINARY(10), + TRACK2(11), + CLIENTSCRIPT(12), + FONTS(13), + VORBIS(14), + INSTRUMENTS(15), + WORLDMAP(16); + + private int id; + + IndexType(int id) + { + this.id = id; + } + + public int getNumber() + { + return id; + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/InterfaceManager.java b/src/main/java/net/runelite/cache/InterfaceManager.java new file mode 100644 index 0000000..ccfcfed --- /dev/null +++ b/src/main/java/net/runelite/cache/InterfaceManager.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import net.runelite.cache.definitions.InterfaceDefinition; +import net.runelite.cache.definitions.exporters.InterfaceExporter; +import net.runelite.cache.definitions.loaders.InterfaceLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; +import net.runelite.cache.util.Namer; + +public class InterfaceManager +{ + private final Store store; + private InterfaceDefinition[][] interfaces; + private final Namer namer = new Namer(); + + public InterfaceManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + InterfaceLoader loader = new InterfaceLoader(); + + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.INTERFACES); + + int max = index.getArchives().stream().mapToInt(a -> a.getArchiveId()).max().getAsInt(); + interfaces = new InterfaceDefinition[max + 1][]; + + for (Archive archive : index.getArchives()) + { + int archiveId = archive.getArchiveId(); + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + InterfaceDefinition[] ifaces = interfaces[archiveId]; + if (ifaces == null) + { + ifaces = interfaces[archiveId] = new InterfaceDefinition[archive.getFileData().length]; + } + + for (FSFile file : files.getFiles()) + { + int fileId = file.getFileId(); + + int widgetId = (archiveId << 16) + fileId; + + InterfaceDefinition iface = loader.load(widgetId, file.getContents()); + ifaces[fileId] = iface; + } + } + } + + public int getNumInterfaceGroups() + { + return interfaces.length; + } + + public int getNumChildren(int groupId) + { + return interfaces[groupId].length; + } + + public InterfaceDefinition[] getIntefaceGroup(int groupId) + { + return interfaces[groupId]; + } + + public InterfaceDefinition getInterface(int groupId, int childId) + { + return interfaces[groupId][childId]; + } + + public InterfaceDefinition[][] getInterfaces() + { + return interfaces; + } + + public void export(File out) throws IOException + { + out.mkdirs(); + + for (InterfaceDefinition[] defs : interfaces) + { + if (defs == null) + { + continue; + } + + for (InterfaceDefinition def : defs) + { + if (def == null) + { + continue; + } + + InterfaceExporter exporter = new InterfaceExporter(def); + + File folder = new File(out, "" + (def.id >>> 16)); + folder.mkdirs(); + + File targ = new File(folder, (def.id & 0xffff) + ".json"); + exporter.exportTo(targ); + } + } + } + + public void java(File java) throws IOException + { + System.setProperty("line.separator", "\n"); + java.mkdirs(); + File targ = new File(java, "InterfaceID.java"); + try (PrintWriter fw = new PrintWriter(targ)) + { + fw.println("/* This file is automatically generated. Do not edit. */"); + fw.println("package net.runelite.api;"); + fw.println(""); + fw.println("public final class InterfaceID {"); + for (InterfaceDefinition[] defs : interfaces) + { + if (defs == null) + { + continue; + } + for (InterfaceDefinition def : defs) + { + if (def == null || def.name == null || def.name.equalsIgnoreCase("NULL")) + { + continue; + } + + String name = namer.name(def.name, def.id); + if (name == null) + { + continue; + } + + fw.println(" public static final int " + name + " = " + def.id + ";"); + } + } + fw.println("}"); + } + } +} diff --git a/src/main/java/net/runelite/cache/InventoryManager.java b/src/main/java/net/runelite/cache/InventoryManager.java new file mode 100644 index 0000000..772d48b --- /dev/null +++ b/src/main/java/net/runelite/cache/InventoryManager.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import net.runelite.cache.definitions.InventoryDefinition; +import net.runelite.cache.definitions.loaders.InventoryLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; + +public class InventoryManager +{ + private final Store store; + private final List inventories = new ArrayList<>(); + + public InventoryManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + InventoryLoader loader = new InventoryLoader(); + + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.INV.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile file : files.getFiles()) + { + InventoryDefinition inv = loader.load(file.getFileId(), file.getContents()); + inventories.add(inv); + } + } + + public List getInventories() + { + return Collections.unmodifiableList(inventories); + } + + public InventoryDefinition findInventory(int id) + { + for (InventoryDefinition def : inventories) + { + if (def.id == id) + { + return def; + } + } + return null; + } +} diff --git a/src/main/java/net/runelite/cache/ItemManager.java b/src/main/java/net/runelite/cache/ItemManager.java new file mode 100644 index 0000000..b3449a5 --- /dev/null +++ b/src/main/java/net/runelite/cache/ItemManager.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.ItemDefinition; +import net.runelite.cache.definitions.exporters.ItemExporter; +import net.runelite.cache.definitions.loaders.ItemLoader; +import net.runelite.cache.definitions.providers.ItemProvider; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; +import net.runelite.cache.util.IDClass; + +public class ItemManager implements ItemProvider +{ + private final Store store; + private final Map items = new HashMap<>(); + + public ItemManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + ItemLoader loader = new ItemLoader(); + + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.ITEM.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile f : files.getFiles()) + { + ItemDefinition def = loader.load(f.getFileId(), f.getContents()); + items.put(f.getFileId(), def); + } + } + + public Collection getItems() + { + return Collections.unmodifiableCollection(items.values()); + } + + public ItemDefinition getItem(int itemId) + { + return items.get(itemId); + } + + public void export(File out) throws IOException + { + out.mkdirs(); + + for (ItemDefinition def : items.values()) + { + ItemExporter exporter = new ItemExporter(def); + + File targ = new File(out, def.id + ".json"); + exporter.exportTo(targ); + } + } + + public void java(File java) throws IOException + { + java.mkdirs(); + try (IDClass ids = IDClass.create(java, "ItemID")) + { + try (IDClass nulls = IDClass.create(java, "NullItemID")) + { + for (ItemDefinition def : items.values()) + { + if (def.name.equalsIgnoreCase("NULL")) + { + nulls.add(def.name, def.id); + } + else + { + ids.add(def.name, def.id); + } + } + } + } + } + + @Override + public ItemDefinition provide(int itemId) + { + return getItem(itemId); + } +} diff --git a/src/main/java/net/runelite/cache/MapImageDumper.java b/src/main/java/net/runelite/cache/MapImageDumper.java new file mode 100644 index 0000000..af857e7 --- /dev/null +++ b/src/main/java/net/runelite/cache/MapImageDumper.java @@ -0,0 +1,987 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import lombok.Getter; +import lombok.Setter; +import net.runelite.cache.definitions.AreaDefinition; +import net.runelite.cache.definitions.ObjectDefinition; +import net.runelite.cache.definitions.OverlayDefinition; +import net.runelite.cache.definitions.SpriteDefinition; +import net.runelite.cache.definitions.UnderlayDefinition; +import net.runelite.cache.definitions.loaders.OverlayLoader; +import net.runelite.cache.definitions.loaders.SpriteLoader; +import net.runelite.cache.definitions.loaders.UnderlayLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; +import net.runelite.cache.item.ColorPalette; +import net.runelite.cache.item.RSTextureProvider; +import net.runelite.cache.region.Location; +import net.runelite.cache.region.Region; +import net.runelite.cache.region.RegionLoader; +import net.runelite.cache.util.Djb2; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MapImageDumper +{ + private static final Logger logger = LoggerFactory.getLogger(MapImageDumper.class); + + private static final int MAP_SCALE = 4; // this squared is the number of pixels per map square + private static final int MAPICON_MAX_WIDTH = 5; // scale minimap icons down to this size so they fit.. + private static final int MAPICON_MAX_HEIGHT = 6; + private static final int BLEND = 5; // number of surrounding tiles for ground blending + + private static int[] colorPalette = new ColorPalette(0.9d, 0, 512).getColorPalette(); + + private static int[][] TILE_SHAPE_2D = new int[][]{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1}, {1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1}, {0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0}, {1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1}, {1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1}}; + private static int[][] TILE_ROTATION_2D = new int[][]{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, {12, 8, 4, 0, 13, 9, 5, 1, 14, 10, 6, 2, 15, 11, 7, 3}, {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, {3, 7, 11, 15, 2, 6, 10, 14, 1, 5, 9, 13, 0, 4, 8, 12}}; + + private final int wallColor = (238 + (int) (Math.random() * 20.0D) - 10 << 16) + (238 + (int) (Math.random() * 20.0D) - 10 << 8) + (238 + (int) (Math.random() * 20.0D) - 10); + private final int doorColor = 238 + (int) (Math.random() * 20.0D) - 10 << 16; + + private final Store store; + + private final Map underlays = new HashMap<>(); + private final Map overlays = new HashMap<>(); + private final Map scaledMapIcons = new HashMap<>(); + + private RegionLoader regionLoader; + private final AreaManager areas; + private final SpriteManager sprites; + private RSTextureProvider rsTextureProvider; + private final ObjectManager objectManager; + + @Getter + @Setter + private boolean labelRegions; + + @Getter + @Setter + private boolean outlineRegions; + + public MapImageDumper(Store store) + { + this.store = store; + this.areas = new AreaManager(store); + this.sprites = new SpriteManager(store); + objectManager = new ObjectManager(store); + } + + public void load() throws IOException + { + loadUnderlays(store); + loadOverlays(store); + objectManager.load(); + + TextureManager textureManager = new TextureManager(store); + textureManager.load(); + rsTextureProvider = new RSTextureProvider(textureManager, sprites); + + loadRegions(store); + areas.load(); + sprites.load(); + loadSprites(); + } + + public BufferedImage drawMap(int z) + { + int minX = regionLoader.getLowestX().getBaseX(); + int minY = regionLoader.getLowestY().getBaseY(); + + int maxX = regionLoader.getHighestX().getBaseX() + Region.X; + int maxY = regionLoader.getHighestY().getBaseY() + Region.Y; + + int dimX = maxX - minX; + int dimY = maxY - minY; + + int pixelsX = dimX * MAP_SCALE; + int pixelsY = dimY * MAP_SCALE; + + logger.info("Map image dimensions: {}px x {}px, {}px per map square ({} MB). Max memory: {}mb", pixelsX, pixelsY, + MAP_SCALE, (pixelsX * pixelsY * 3 / 1024 / 1024), + Runtime.getRuntime().maxMemory() / 1024L / 1024L); + + BufferedImage image = new BufferedImage(pixelsX, pixelsY, BufferedImage.TYPE_INT_RGB); + + drawMap(image, z); + drawObjects(image, z); + drawMapIcons(image, z); + + return image; + } + + public BufferedImage drawRegion(Region region, int z) + { + int pixelsX = Region.X * MAP_SCALE; + int pixelsY = Region.Y * MAP_SCALE; + + BufferedImage image = new BufferedImage(pixelsX, pixelsY, BufferedImage.TYPE_INT_RGB); + + drawMap(image, 0, 0, z, region); + drawObjects(image, 0, 0, region, z); + drawMapIcons(image, 0, 0, region, z); + + return image; + } + + private void drawMap(BufferedImage image, int drawBaseX, int drawBaseY, int z, Region region) + { + int[][] map = new int[Region.X * MAP_SCALE][Region.Y * MAP_SCALE]; + drawMap(map, region, z); + + int[][] above = null; + if (z < 3) + { + above = new int[Region.X * MAP_SCALE][Region.Y * MAP_SCALE]; + drawMap(above, region, z + 1); + } + + for (int x = 0; x < Region.X; ++x) + { + for (int y = 0; y < Region.Y; ++y) + { + boolean isBridge = (region.getTileSetting(1, x, Region.Y - y - 1) & 2) != 0; + + int tileSetting = region.getTileSetting(z, x, Region.Y - y - 1); + if (!isBridge && ((tileSetting & 24) == 0)) + { + drawTile(image, map, drawBaseX, drawBaseY, x, y); + } + + if (z < 3 && isBridge) // client also has a check for &8 != 0 here + { + drawTile(image, above, drawBaseX, drawBaseY, x, y); + } + } + } + } + + private void drawMap(BufferedImage image, int z) + { + for (Region region : regionLoader.getRegions()) + { + int baseX = region.getBaseX(); + int baseY = region.getBaseY(); + + // to pixel X + int drawBaseX = baseX - regionLoader.getLowestX().getBaseX(); + + // to pixel Y. top most y is 0, but the top most + // region has the greatest y, so invert + int drawBaseY = regionLoader.getHighestY().getBaseY() - baseY; + + drawMap(image, drawBaseX, drawBaseY, z, region); + } + } + + private void drawTile(BufferedImage to, int[][] pixels, int drawBaseX, int drawBaseY, int x, int y) + { + for (int i = 0; i < MAP_SCALE; ++i) + { + for (int j = 0; j < MAP_SCALE; ++j) + { + to.setRGB(drawBaseX * MAP_SCALE + x * MAP_SCALE + i, + drawBaseY * MAP_SCALE + y * MAP_SCALE + j, + pixels[x * MAP_SCALE + i][y * MAP_SCALE + j]); + } + } + } + + private void drawMap(int[][] pixels, Region region, int z) + { + int baseX = region.getBaseX(); + int baseY = region.getBaseY(); + + int len = Region.X + BLEND * 2; + int[] hues = new int[len]; + int[] sats = new int[len]; + int[] light = new int[len]; + int[] mul = new int[len]; + int[] num = new int[len]; + + boolean hasLeftRegion = regionLoader.findRegionForWorldCoordinates(baseX - 1, baseY) != null; + boolean hasRightRegion = regionLoader.findRegionForWorldCoordinates(baseX + Region.X, baseY) != null; + boolean hasUpRegion = regionLoader.findRegionForWorldCoordinates(baseX, baseY + Region.Y) != null; + boolean hasDownRegion = regionLoader.findRegionForWorldCoordinates(baseX, baseY - 1) != null; + + for (int xi = (hasLeftRegion ? -BLEND * 2 : -BLEND); xi < Region.X + (hasRightRegion ? BLEND * 2 : BLEND); ++xi) + { + for (int yi = (hasDownRegion ? -BLEND : 0); yi < Region.Y + (hasUpRegion ? BLEND : 0); ++yi) + { + int xr = xi + BLEND; + if (xr >= (hasLeftRegion ? -BLEND : 0) && xr < Region.X + (hasRightRegion ? BLEND : 0)) + { + Region r = regionLoader.findRegionForWorldCoordinates(baseX + xr, baseY + yi); + if (r != null) + { + int underlayId = r.getUnderlayId(z, convert(xr), convert(yi)); + if (underlayId > 0) + { + UnderlayDefinition underlay = findUnderlay(underlayId - 1); + hues[yi + BLEND] += underlay.getHue(); + sats[yi + BLEND] += underlay.getSaturation(); + light[yi + BLEND] += underlay.getLightness(); + mul[yi + BLEND] += underlay.getHueMultiplier(); + num[yi + BLEND]++; + } + } + } + + int xl = xi - BLEND; + if (xl >= (hasLeftRegion ? -BLEND : 0) && xl < Region.X + (hasRightRegion ? BLEND : 0)) + { + Region r = regionLoader.findRegionForWorldCoordinates(baseX + xl, baseY + yi); + if (r != null) + { + int underlayId = r.getUnderlayId(z, convert(xl), convert(yi)); + if (underlayId > 0) + { + UnderlayDefinition underlay = findUnderlay(underlayId - 1); + hues[yi + BLEND] -= underlay.getHue(); + sats[yi + BLEND] -= underlay.getSaturation(); + light[yi + BLEND] -= underlay.getLightness(); + mul[yi + BLEND] -= underlay.getHueMultiplier(); + num[yi + BLEND]--; + } + } + } + } + + if (xi >= 0 && xi < Region.X) + { + int runningHues = 0; + int runningSat = 0; + int runningLight = 0; + int runningMultiplier = 0; + int runningNumber = 0; + + for (int yi = (hasDownRegion ? -BLEND * 2 : -BLEND); yi < Region.Y + (hasUpRegion ? BLEND * 2 : BLEND); ++yi) + { + int yu = yi + BLEND; + if (yu >= (hasDownRegion ? -BLEND : 0) && yu < Region.Y + (hasUpRegion ? BLEND : 0)) + { + runningHues += hues[yu + BLEND]; + runningSat += sats[yu + BLEND]; + runningLight += light[yu + BLEND]; + runningMultiplier += mul[yu + BLEND]; + runningNumber += num[yu + BLEND]; + } + + int yd = yi - BLEND; + if (yd >= (hasDownRegion ? -BLEND : 0) && yd < Region.Y + (hasUpRegion ? BLEND : 0)) + { + runningHues -= hues[yd + BLEND]; + runningSat -= sats[yd + BLEND]; + runningLight -= light[yd + BLEND]; + runningMultiplier -= mul[yd + BLEND]; + runningNumber -= num[yd + BLEND]; + } + + if (yi >= 0 && yi < Region.Y) + { + Region r = regionLoader.findRegionForWorldCoordinates(baseX + xi, baseY + yi); + if (r != null) + { + int underlayId = r.getUnderlayId(z, convert(xi), convert(yi)); + int overlayId = r.getOverlayId(z, convert(xi), convert(yi)); + + if (underlayId > 0 || overlayId > 0) + { + int underlayHsl = -1; + if (underlayId > 0) + { + int avgHue = runningHues * 256 / runningMultiplier; + int avgSat = runningSat / runningNumber; + int avgLight = runningLight / runningNumber; + // randomness is added to avgHue here + + if (avgLight < 0) + { + avgLight = 0; + } + else if (avgLight > 255) + { + avgLight = 255; + } + + underlayHsl = packHsl(avgHue, avgSat, avgLight); + } + + int underlayRgb = 0; + if (underlayHsl != -1) + { + int var0 = method1792(underlayHsl, 96); + underlayRgb = colorPalette[var0]; + } + + int shape, rotation; + Integer overlayRgb = null; + if (overlayId == 0) + { + shape = rotation = 0; + } + else + { + shape = r.getOverlayPath(z, convert(xi), convert(yi)) + 1; + rotation = r.getOverlayRotation(z, convert(xi), convert(yi)); + + OverlayDefinition overlayDefinition = findOverlay(overlayId - 1); + int overlayTexture = overlayDefinition.getTexture(); + int rgb; + + if (overlayTexture >= 0) + { + rgb = rsTextureProvider.getAverageTextureRGB(overlayTexture); + } + else if (overlayDefinition.getRgbColor() == 0xFF_00FF) + { + rgb = -2; + } + else + { + // randomness added here + int overlayHsl = packHsl(overlayDefinition.getHue(), overlayDefinition.getSaturation(), overlayDefinition.getLightness()); + rgb = overlayHsl; + } + + overlayRgb = 0; + if (rgb != -2) + { + int var0 = adjustHSLListness0(rgb, 96); + overlayRgb = colorPalette[var0]; + } + + if (overlayDefinition.getSecondaryRgbColor() != -1) + { + int hue = overlayDefinition.getOtherHue(); + int sat = overlayDefinition.getOtherSaturation(); + int olight = overlayDefinition.getOtherLightness(); + rgb = packHsl(hue, sat, olight); + int var0 = adjustHSLListness0(rgb, 96); + overlayRgb = colorPalette[var0]; + } + } + + if (shape == 0) + { + int drawX = xi; + int drawY = Region.Y - 1 - yi; + if (underlayRgb != 0) + { + drawMapSquare(pixels, drawX, drawY, underlayRgb); + } + } + else if (shape == 1) + { + int drawX = xi; + int drawY = Region.Y - 1 - yi; + drawMapSquare(pixels, drawX, drawY, overlayRgb); + } + else + { + int drawX = xi * MAP_SCALE; + int drawY = (Region.Y - 1 - yi) * MAP_SCALE; + int[] tileShapes = TILE_SHAPE_2D[shape]; + int[] tileRotations = TILE_ROTATION_2D[rotation]; + if (underlayRgb != 0) + { + int rotIdx = 0; + for (int i = 0; i < Region.Z; ++i) + { + int p1 = tileShapes[tileRotations[rotIdx++]] == 0 ? underlayRgb : overlayRgb; + int p2 = tileShapes[tileRotations[rotIdx++]] == 0 ? underlayRgb : overlayRgb; + int p3 = tileShapes[tileRotations[rotIdx++]] == 0 ? underlayRgb : overlayRgb; + int p4 = tileShapes[tileRotations[rotIdx++]] == 0 ? underlayRgb : overlayRgb; + pixels[drawX + 0][drawY + i] = p1; + pixels[drawX + 1][drawY + i] = p2; + pixels[drawX + 2][drawY + i] = p3; + pixels[drawX + 3][drawY + i] = p4; + } + } + else + { + int rotIdx = 0; + for (int i = 0; i < Region.Z; ++i) + { + int p1 = tileShapes[tileRotations[rotIdx++]]; + int p2 = tileShapes[tileRotations[rotIdx++]]; + int p3 = tileShapes[tileRotations[rotIdx++]]; + int p4 = tileShapes[tileRotations[rotIdx++]]; + + if (p1 != 0) + { + pixels[drawX + 0][drawY + i] = overlayRgb; + } + + if (p2 != 0) + { + pixels[drawX + 1][drawY + i] = overlayRgb; + } + + if (p3 != 0) + { + pixels[drawX + 2][drawY + i] = overlayRgb; + } + + if (p4 != 0) + { + pixels[drawX + 3][drawY + i] = overlayRgb; + } + } + } + } + } + } + } + } + } + } + } + + private static int convert(int d) + { + if (d >= 0) + { + return d % 64; + } + else + { + return 64 - -(d % 64) - 1; + } + } + + private void drawObjects(BufferedImage image, int drawBaseX, int drawBaseY, Region region, int z) + { + Graphics2D graphics = image.createGraphics(); + + for (Location location : region.getLocations()) + { + + int rotation = location.getOrientation(); + int type = location.getType(); + + int localX = location.getPosition().getX() - region.getBaseX(); + int localY = location.getPosition().getY() - region.getBaseY(); + + boolean isBridge = (region.getTileSetting(1, localX, localY) & 2) != 0; + + if (location.getPosition().getZ() == z + 1) + { + if (!isBridge) + { + continue; + } + } + else if (location.getPosition().getZ() == z) + { + if (isBridge) + { + continue; + } + + if ((region.getTileSetting(z, localX, localY) & 24) != 0) + { + continue; + } + } + else + { + continue; + } + + ObjectDefinition object = findObject(location.getId()); + + int drawX = (drawBaseX + localX) * MAP_SCALE; + int drawY = (drawBaseY + (Region.Y - 1 - localY)) * MAP_SCALE; + + if (type >= 0 && type <= 3) + { + // this is a wall + int hash = (localY << 7) + localX + (location.getId() << 14) + 0x4000_0000; + if (object.getWallOrDoor() == 0) + { + hash -= Integer.MIN_VALUE; + } + + int rgb = wallColor; + if (hash > 0) + { + rgb = doorColor; + } + + if (object.getMapSceneID() != -1) + { + Image spriteImage = scaledMapIcons.get(object.getMapSceneID()); + graphics.drawImage(spriteImage, drawX * MAP_SCALE, drawY * MAP_SCALE, null); + } + else + { + if (type == 0 || type == 2) + { + if (rotation == 0) + { + image.setRGB(drawX + 0, drawY + 0, rgb); + image.setRGB(drawX + 0, drawY + 1, rgb); + image.setRGB(drawX + 0, drawY + 2, rgb); + image.setRGB(drawX + 0, drawY + 3, rgb); + } + else if (rotation == 1) + { + image.setRGB(drawX + 0, drawY + 0, rgb); + image.setRGB(drawX + 1, drawY + 0, rgb); + image.setRGB(drawX + 2, drawY + 0, rgb); + image.setRGB(drawX + 3, drawY + 0, rgb); + } + else if (rotation == 2) + { + image.setRGB(drawX + 3, drawY + 0, rgb); + image.setRGB(drawX + 3, drawY + 1, rgb); + image.setRGB(drawX + 3, drawY + 2, rgb); + image.setRGB(drawX + 3, drawY + 3, rgb); + } + else if (rotation == 3) + { + image.setRGB(drawX + 0, drawY + 3, rgb); + image.setRGB(drawX + 1, drawY + 3, rgb); + image.setRGB(drawX + 2, drawY + 3, rgb); + image.setRGB(drawX + 3, drawY + 3, rgb); + } + } + + if (type == 3) + { + if (rotation == 0) + { + image.setRGB(drawX + 0, drawY + 0, rgb); + } + else if (rotation == 1) + { + image.setRGB(drawX + 3, drawY + 0, rgb); + } + else if (rotation == 2) + { + image.setRGB(drawX + 3, drawY + 3, rgb); + } + else if (rotation == 3) + { + image.setRGB(drawX + 0, drawY + 3, rgb); + } + } + + if (type == 2) + { + if (rotation == 3) + { + image.setRGB(drawX + 0, drawY + 0, rgb); + image.setRGB(drawX + 0, drawY + 1, rgb); + image.setRGB(drawX + 0, drawY + 2, rgb); + image.setRGB(drawX + 0, drawY + 3, rgb); + } + else if (rotation == 0) + { + image.setRGB(drawX + 0, drawY + 0, rgb); + image.setRGB(drawX + 1, drawY + 0, rgb); + image.setRGB(drawX + 2, drawY + 0, rgb); + image.setRGB(drawX + 3, drawY + 0, rgb); + } + else if (rotation == 1) + { + image.setRGB(drawX + 3, drawY + 0, rgb); + image.setRGB(drawX + 3, drawY + 1, rgb); + image.setRGB(drawX + 3, drawY + 2, rgb); + image.setRGB(drawX + 3, drawY + 3, rgb); + } + else if (rotation == 2) + { + image.setRGB(drawX + 0, drawY + 3, rgb); + image.setRGB(drawX + 1, drawY + 3, rgb); + image.setRGB(drawX + 2, drawY + 3, rgb); + image.setRGB(drawX + 3, drawY + 3, rgb); + } + } + } + } + else if (type == 9) + { + if (object.getMapSceneID() != -1) + { + Image spriteImage = scaledMapIcons.get(object.getMapSceneID()); + graphics.drawImage(spriteImage, drawX, drawY, null); + continue; + } + + int hash = (localY << 7) + localX + (location.getId() << 14) + 0x4000_0000; + if (object.getWallOrDoor() == 0) + { + hash -= Integer.MIN_VALUE; + } + + if ((hash >> 29 & 3) != 2) + { + continue; + } + + int rgb = 0xEE_EEEE; + if (hash > 0) + { + rgb = 0xEE_0000; + } + + if (rotation != 0 && rotation != 2) + { + image.setRGB(drawX + 0, drawY + 0, rgb); + image.setRGB(drawX + 1, drawY + 1, rgb); + image.setRGB(drawX + 2, drawY + 2, rgb); + image.setRGB(drawX + 3, drawY + 3, rgb); + } + else + { + image.setRGB(drawX + 0, drawY + 3, rgb); + image.setRGB(drawX + 1, drawY + 2, rgb); + image.setRGB(drawX + 2, drawY + 1, rgb); + image.setRGB(drawX + 3, drawY + 0, rgb); + } + } + else if (type == 22 || (type >= 9 && type <= 11)) + { + // ground object + if (object.getMapSceneID() != -1) + { + Image spriteImage = scaledMapIcons.get(object.getMapSceneID()); + graphics.drawImage(spriteImage, drawX, drawY, null); + } + } + } + + graphics.dispose(); + } + + private void drawObjects(BufferedImage image, int z) + { + for (Region region : regionLoader.getRegions()) + { + int baseX = region.getBaseX(); + int baseY = region.getBaseY(); + + // to pixel X + int drawBaseX = baseX - regionLoader.getLowestX().getBaseX(); + + // to pixel Y. top most y is 0, but the top most + // region has the greatest y, so invert + int drawBaseY = regionLoader.getHighestY().getBaseY() - baseY; + + drawObjects(image, drawBaseX, drawBaseY, region, z); + } + } + + private void drawMapIcons(BufferedImage image, int drawBaseX, int drawBaseY, Region region, int z) + { + int baseX = region.getBaseX(); + int baseY = region.getBaseY(); + + Graphics2D graphics = image.createGraphics(); + + drawMapIcons(graphics, region, z, drawBaseX, drawBaseY); + + if (labelRegions) + { + graphics.setColor(Color.WHITE); + String str = baseX + "," + baseY + " (" + region.getRegionX() + "," + region.getRegionY() + ")"; + graphics.drawString(str, drawBaseX * MAP_SCALE, drawBaseY * MAP_SCALE + graphics.getFontMetrics().getHeight()); + } + + if (outlineRegions) + { + graphics.setColor(Color.WHITE); + graphics.drawRect(drawBaseX * MAP_SCALE, drawBaseY * MAP_SCALE, Region.X * MAP_SCALE, Region.Y * MAP_SCALE); + } + + graphics.dispose(); + } + + private void drawMapIcons(BufferedImage image, int z) + { + // map icons + for (Region region : regionLoader.getRegions()) + { + int baseX = region.getBaseX(); + int baseY = region.getBaseY(); + + // to pixel X + int drawBaseX = baseX - regionLoader.getLowestX().getBaseX(); + + // to pixel Y. top most y is 0, but the top most + // region has the greatest y, so invert + int drawBaseY = regionLoader.getHighestY().getBaseY() - baseY; + + drawMapIcons(image, drawBaseX, drawBaseY, region, z); + } + } + + private ObjectDefinition findObject(int id) + { + return objectManager.getObject(id); + } + + private int packHsl(int var0, int var1, int var2) + { + if (var2 > 179) + { + var1 /= 2; + } + + if (var2 > 192) + { + var1 /= 2; + } + + if (var2 > 217) + { + var1 /= 2; + } + + if (var2 > 243) + { + var1 /= 2; + } + + int var3 = (var1 / 32 << 7) + (var0 / 4 << 10) + var2 / 2; + return var3; + } + + static int method1792(int var0, int var1) + { + if (var0 == -1) + { + return 12345678; + } + else + { + var1 = (var0 & 127) * var1 / 128; + if (var1 < 2) + { + var1 = 2; + } + else if (var1 > 126) + { + var1 = 126; + } + + return (var0 & 65408) + var1; + } + } + + static final int adjustHSLListness0(int var0, int var1) + { + if (var0 == -2) + { + return 12345678; + } + else if (var0 == -1) + { + if (var1 < 2) + { + var1 = 2; + } + else if (var1 > 126) + { + var1 = 126; + } + + return var1; + } + else + { + var1 = (var0 & 127) * var1 / 128; + if (var1 < 2) + { + var1 = 2; + } + else if (var1 > 126) + { + var1 = 126; + } + + return (var0 & 65408) + var1; + } + } + + private void drawMapSquare(int[][] pixels, int x, int y, int rgb) + { + x *= MAP_SCALE; + y *= MAP_SCALE; + + for (int i = 0; i < MAP_SCALE; ++i) + { + for (int j = 0; j < MAP_SCALE; ++j) + { + pixels[x + i][y + j] = rgb; + } + } + } + + private void drawMapIcons(Graphics2D graphics, Region region, int z, int drawBaseX, int drawBaseY) + { + for (Location location : region.getLocations()) + { + int localZ = location.getPosition().getZ(); + if (z != 0 && localZ != z) + { + // draw all icons on z=0 + continue; + } + + ObjectDefinition od = findObject(location.getId()); + + assert od != null; + + int localX = location.getPosition().getX() - region.getBaseX(); + int localY = location.getPosition().getY() - region.getBaseY(); + + int drawX = drawBaseX + localX; + int drawY = drawBaseY + (Region.Y - 1 - localY); + + if (od.getMapAreaId() != -1) + { + AreaDefinition area = areas.getArea(od.getMapAreaId()); + assert area != null; + + int spriteId = area.spriteId; + + SpriteDefinition sprite = sprites.findSprite(spriteId, 0); + assert sprite != null; + + BufferedImage iconImage = sprites.getSpriteImage(sprite); + graphics.drawImage(iconImage, drawX * MAP_SCALE, drawY * MAP_SCALE, null); + } + } + } + + private void loadRegions(Store store) throws IOException + { + regionLoader = new RegionLoader(store); + regionLoader.loadRegions(); + regionLoader.calculateBounds(); + + logger.info("North most region: {}", regionLoader.getLowestY().getBaseY()); + logger.info("South most region: {}", regionLoader.getHighestY().getBaseY()); + logger.info("West most region: {}", regionLoader.getLowestX().getBaseX()); + logger.info("East most region: {}", regionLoader.getHighestX().getBaseX()); + } + + private void loadUnderlays(Store store) throws IOException + { + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.UNDERLAY.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile file : files.getFiles()) + { + UnderlayLoader loader = new UnderlayLoader(); + UnderlayDefinition underlay = loader.load(file.getFileId(), file.getContents()); + + underlays.put(underlay.getId(), underlay); + } + } + + private UnderlayDefinition findUnderlay(int id) + { + return underlays.get(id); + } + + private void loadOverlays(Store store) throws IOException + { + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.OVERLAY.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile file : files.getFiles()) + { + OverlayLoader loader = new OverlayLoader(); + OverlayDefinition overlay = loader.load(file.getFileId(), file.getContents()); + + overlays.put(overlay.getId(), overlay); + } + } + + private OverlayDefinition findOverlay(int id) + { + return overlays.get(id); + } + + private void loadSprites() throws IOException + { + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.SPRITES); + final int mapsceneHash = Djb2.hash("mapscene"); + + for (Archive a : index.getArchives()) + { + byte[] contents = a.decompress(storage.loadArchive(a)); + + SpriteLoader loader = new SpriteLoader(); + SpriteDefinition[] sprites = loader.load(a.getArchiveId(), contents); + + for (SpriteDefinition sprite : sprites) + { + if (sprite.getHeight() <= 0 || sprite.getWidth() <= 0) + { + continue; + } + + if (a.getNameHash() == mapsceneHash) + { + BufferedImage spriteImage = new BufferedImage(sprite.getWidth(), sprite.getHeight(), BufferedImage.TYPE_INT_ARGB); + spriteImage.setRGB(0, 0, sprite.getWidth(), sprite.getHeight(), sprite.getPixels(), 0, sprite.getWidth()); + + // scale image down so it fits + Image scaledImage = spriteImage.getScaledInstance(MAPICON_MAX_WIDTH, MAPICON_MAX_HEIGHT, 0); + + assert scaledMapIcons.containsKey(sprite.getFrame()) == false; + scaledMapIcons.put(sprite.getFrame(), scaledImage); + } + } + } + } + +} diff --git a/src/main/java/net/runelite/cache/NpcManager.java b/src/main/java/net/runelite/cache/NpcManager.java new file mode 100644 index 0000000..3124eb4 --- /dev/null +++ b/src/main/java/net/runelite/cache/NpcManager.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.NpcDefinition; +import net.runelite.cache.definitions.exporters.NpcExporter; +import net.runelite.cache.definitions.loaders.NpcLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; +import net.runelite.cache.util.IDClass; + +public class NpcManager +{ + private final Store store; + private final Map npcs = new HashMap<>(); + + public NpcManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + NpcLoader loader = new NpcLoader(); + + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.NPC.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile f : files.getFiles()) + { + NpcDefinition npc = loader.load(f.getFileId(), f.getContents()); + npcs.put(f.getFileId(), npc); + } + } + + public Collection getNpcs() + { + return Collections.unmodifiableCollection(npcs.values()); + } + + public NpcDefinition get(int npcId) + { + return npcs.get(npcId); + } + + public void dump(File out) throws IOException + { + out.mkdirs(); + + for (NpcDefinition def : npcs.values()) + { + NpcExporter exporter = new NpcExporter(def); + + File targ = new File(out, def.id + ".json"); + exporter.exportTo(targ); + } + } + + public void java(File java) throws IOException + { + java.mkdirs(); + try (IDClass ids = IDClass.create(java, "NpcID")) + { + for (NpcDefinition def : npcs.values()) + { + if (def.name.equalsIgnoreCase("NULL")) + { + continue; + } + + ids.add(def.name, def.id); + } + } + } +} diff --git a/src/main/java/net/runelite/cache/ObjectManager.java b/src/main/java/net/runelite/cache/ObjectManager.java new file mode 100644 index 0000000..cb1372e --- /dev/null +++ b/src/main/java/net/runelite/cache/ObjectManager.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.ObjectDefinition; +import net.runelite.cache.definitions.exporters.ObjectExporter; +import net.runelite.cache.definitions.loaders.ObjectLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; +import net.runelite.cache.util.IDClass; + +public class ObjectManager +{ + private final Store store; + private final Map objects = new HashMap<>(); + + public ObjectManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + ObjectLoader loader = new ObjectLoader(); + + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.OBJECT.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile f : files.getFiles()) + { + ObjectDefinition def = loader.load(f.getFileId(), f.getContents()); + objects.put(f.getFileId(), def); + } + } + + public Collection getObjects() + { + return Collections.unmodifiableCollection(objects.values()); + } + + public ObjectDefinition getObject(int id) + { + return objects.get(id); + } + + public void dump(File out) throws IOException + { + out.mkdirs(); + + for (ObjectDefinition def : objects.values()) + { + ObjectExporter exporter = new ObjectExporter(def); + + File targ = new File(out, def.getId() + ".json"); + exporter.exportTo(targ); + } + } + + public void java(File java) throws IOException + { + java.mkdirs(); + try (IDClass ids = IDClass.create(java, "ObjectID")) + { + try (IDClass nulls = IDClass.create(java, "NullObjectID")) + { + for (ObjectDefinition def : objects.values()) + { + if ("null".equals(def.getName())) + { + nulls.add(def.getName(), def.getId()); + } + else + { + ids.add(def.getName(), def.getId()); + } + } + } + } + } +} diff --git a/src/main/java/net/runelite/cache/OverlayManager.java b/src/main/java/net/runelite/cache/OverlayManager.java new file mode 100644 index 0000000..6940227 --- /dev/null +++ b/src/main/java/net/runelite/cache/OverlayManager.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.OverlayDefinition; +import net.runelite.cache.definitions.loaders.OverlayLoader; +import net.runelite.cache.definitions.providers.OverlayProvider; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; + +public class OverlayManager implements OverlayProvider +{ + private final Store store; + private final Map overlays = new HashMap<>(); + + public OverlayManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.OVERLAY.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile file : files.getFiles()) + { + OverlayLoader loader = new OverlayLoader(); + OverlayDefinition overlay = loader.load(file.getFileId(), file.getContents()); + + overlays.put(overlay.getId(), overlay); + } + } + + public Collection getOverlays() + { + return Collections.unmodifiableCollection(overlays.values()); + } + + @Override + public OverlayDefinition provide(int overlayId) + { + return overlays.get(overlayId); + } +} diff --git a/src/main/java/net/runelite/cache/SpriteManager.java b/src/main/java/net/runelite/cache/SpriteManager.java new file mode 100644 index 0000000..a18dd4f --- /dev/null +++ b/src/main/java/net/runelite/cache/SpriteManager.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import com.google.common.collect.LinkedListMultimap; +import com.google.common.collect.Multimap; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import net.runelite.cache.definitions.SpriteDefinition; +import net.runelite.cache.definitions.exporters.SpriteExporter; +import net.runelite.cache.definitions.loaders.SpriteLoader; +import net.runelite.cache.definitions.providers.SpriteProvider; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; + +public class SpriteManager implements SpriteProvider +{ + private final Store store; + private final Multimap sprites = LinkedListMultimap.create(); + + public SpriteManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.SPRITES); + + for (Archive a : index.getArchives()) + { + byte[] contents = a.decompress(storage.loadArchive(a)); + + SpriteLoader loader = new SpriteLoader(); + SpriteDefinition[] defs = loader.load(a.getArchiveId(), contents); + + for (SpriteDefinition sprite : defs) + { + sprites.put(sprite.getId(), sprite); + } + } + } + + public Collection getSprites() + { + return Collections.unmodifiableCollection(sprites.values()); + } + + public SpriteDefinition findSprite(int spriteId, int frameId) + { + for (SpriteDefinition sprite : sprites.get(spriteId)) + { + if (sprite.getFrame() == frameId) + { + return sprite; + } + } + return null; + } + + public BufferedImage getSpriteImage(SpriteDefinition sprite) + { + BufferedImage image = new BufferedImage(sprite.getWidth(), sprite.getHeight(), BufferedImage.TYPE_INT_ARGB); + image.setRGB(0, 0, sprite.getWidth(), sprite.getHeight(), sprite.getPixels(), 0, sprite.getWidth()); + return image; + } + + public void export(File outDir) throws IOException + { + for (SpriteDefinition sprite : sprites.values()) + { + // I don't know why this happens + if (sprite.getHeight() <= 0 || sprite.getWidth() <= 0) + { + continue; + } + + SpriteExporter exporter = new SpriteExporter(sprite); + File png = new File(outDir, sprite.getId() + "-" + sprite.getFrame() + ".png"); + + exporter.exportTo(png); + } + } + + @Override + public SpriteDefinition provide(int spriteId, int frameId) + { + return findSprite(spriteId, frameId); + } +} diff --git a/src/main/java/net/runelite/cache/StructManager.java b/src/main/java/net/runelite/cache/StructManager.java new file mode 100644 index 0000000..bd816a4 --- /dev/null +++ b/src/main/java/net/runelite/cache/StructManager.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, Joshua Filby + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.StructDefinition; +import net.runelite.cache.definitions.loaders.StructLoader; +import net.runelite.cache.definitions.providers.StructProvider; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; + +public class StructManager implements StructProvider +{ + private final Store store; + private final Map structs = new HashMap<>(); + + public StructManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + StructLoader loader = new StructLoader(); + + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.STRUCT.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile f : files.getFiles()) + { + StructDefinition def = loader.load(f.getFileId(), f.getContents()); + structs.put(f.getFileId(), def); + } + } + + public Map getStructs() + { + return Collections.unmodifiableMap(structs); + } + + public StructDefinition getStruct(int structId) + { + return structs.get(structId); + } + + @Override + public StructDefinition provide(int structId) + { + return getStruct(structId); + } +} diff --git a/src/main/java/net/runelite/cache/TextureManager.java b/src/main/java/net/runelite/cache/TextureManager.java new file mode 100644 index 0000000..9eeb350 --- /dev/null +++ b/src/main/java/net/runelite/cache/TextureManager.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import net.runelite.cache.definitions.TextureDefinition; +import net.runelite.cache.definitions.loaders.TextureLoader; +import net.runelite.cache.definitions.providers.TextureProvider; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; + +public class TextureManager implements TextureProvider +{ + private final Store store; + private final List textures = new ArrayList<>(); + + public TextureManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.TEXTURES); + Archive archive = index.getArchive(0); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + TextureLoader loader = new TextureLoader(); + + for (FSFile file : files.getFiles()) + { + TextureDefinition texture = loader.load(file.getFileId(), file.getContents()); + textures.add(texture); + } + } + + public List getTextures() + { + return textures; + } + + public TextureDefinition findTexture(int id) + { + for (TextureDefinition td : textures) + { + if (td.getId() == id) + { + return td; + } + } + return null; + } + + @Override + public TextureDefinition[] provide() + { + return textures.toArray(new TextureDefinition[textures.size()]); + } +} diff --git a/src/main/java/net/runelite/cache/UnderlayManager.java b/src/main/java/net/runelite/cache/UnderlayManager.java new file mode 100644 index 0000000..3bba223 --- /dev/null +++ b/src/main/java/net/runelite/cache/UnderlayManager.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.UnderlayDefinition; +import net.runelite.cache.definitions.loaders.UnderlayLoader; +import net.runelite.cache.definitions.providers.UnderlayProvider; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; + +public class UnderlayManager implements UnderlayProvider +{ + private final Store store; + private final Map underlays = new HashMap<>(); + + public UnderlayManager(Store store) + { + this.store = store; + } + + public void load() throws IOException + { + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.UNDERLAY.getId()); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile file : files.getFiles()) + { + UnderlayLoader loader = new UnderlayLoader(); + UnderlayDefinition underlay = loader.load(file.getFileId(), file.getContents()); + + underlays.put(underlay.getId(), underlay); + } + } + + public Collection getUnderlays() + { + return Collections.unmodifiableCollection(underlays.values()); + } + + @Override + public UnderlayDefinition provide(int underlayId) + { + return underlays.get(underlayId); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/AreaDefinition.java b/src/main/java/net/runelite/cache/definitions/AreaDefinition.java new file mode 100644 index 0000000..7abdbdf --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/AreaDefinition.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class AreaDefinition +{ + public int id; + public int[] field3292; + public int spriteId = -1; + public int field3294 = -1; + public String name; + public int field3296; + public int field3297 = -1; + public String[] field3298 = new String[5]; + public int[] field3300; + public String field3308; + public byte[] field3309; + public int field3310; + +} diff --git a/src/main/java/net/runelite/cache/definitions/ClientScript1Instruction.java b/src/main/java/net/runelite/cache/definitions/ClientScript1Instruction.java new file mode 100644 index 0000000..b56c0a4 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/ClientScript1Instruction.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@Data +public class ClientScript1Instruction +{ + @RequiredArgsConstructor + public enum Opcode + { + RETURN(0), + BOOSTED_SKILL_LEVELS(1), + REAL_SKILL_LEVELS(1), + SKILL_EXPERIENCE(1), + WIDGET_CONTAINS_ITEM_GET_QUANTITY(3), + VARP(1), + EXPERIENCE_AT_LEVEL_FOR_SKILL(1), + VARP_TIMES_469(1), + COMBAT_LEVEL(1), + TOTAL_LEVEL(0), + WIDGET_CONTAINS_ITEM_STAR(3), + RUN_ENERGY(0), + WEIGHT(0), + VARP_TESTBIT(2), + VARBIT(1), + MINUS(0), + DIV(0), + MUL(0), + WORLD_X(0), + WORLD_Y(1), + CONSTANT(1); + + public final int argumentCount; + } + + public Opcode opcode; + public int[] operands; +} diff --git a/src/main/java/net/runelite/cache/definitions/EnumDefinition.java b/src/main/java/net/runelite/cache/definitions/EnumDefinition.java new file mode 100644 index 0000000..e9f1c11 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/EnumDefinition.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.definitions; + +import lombok.Data; +import net.runelite.cache.util.ScriptVarType; + +@Data +public class EnumDefinition +{ + private int id; + private int[] intVals; + private ScriptVarType keyType; + private ScriptVarType valType; + private String defaultString = "null"; + private int defaultInt; + private int size; + private int[] keys; + private String[] stringVals; +} diff --git a/src/main/java/net/runelite/cache/definitions/FrameDefinition.java b/src/main/java/net/runelite/cache/definitions/FrameDefinition.java new file mode 100644 index 0000000..c31f033 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/FrameDefinition.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class FrameDefinition +{ + public int id; // file id + public FramemapDefinition framemap; + public int[] translator_x; + public int[] translator_y; + public int[] translator_z; + public int translatorCount = -1; + public int[] indexFrameIds; + public boolean showing; +} diff --git a/src/main/java/net/runelite/cache/definitions/FramemapDefinition.java b/src/main/java/net/runelite/cache/definitions/FramemapDefinition.java new file mode 100644 index 0000000..00669d6 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/FramemapDefinition.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class FramemapDefinition +{ + public int id; + public int[] types; + public int[][] frameMaps; + public int length; +} diff --git a/src/main/java/net/runelite/cache/definitions/InterfaceDefinition.java b/src/main/java/net/runelite/cache/definitions/InterfaceDefinition.java new file mode 100644 index 0000000..aede6d6 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/InterfaceDefinition.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class InterfaceDefinition +{ + public int id = -1; + public boolean isIf3 = false; + public int type; + public int contentType; + public int originalX; + public int originalY; + public int originalWidth; + public int originalHeight; + public int widthMode; + public int heightMode; + public int xPositionMode; + public int yPositionMode; + public int parentId = -1; + public boolean isHidden; + public int scrollWidth; + public int scrollHeight; + public boolean noClickThrough; + public int spriteId; + public int textureId; + public boolean spriteTiling; + public int opacity; + public int borderType; + public int shadowColor; + public boolean flippedVertically; + public boolean flippedHorizontally; + public int modelType; + public int modelId; + public int offsetX2d; + public int offsetY2d; + public int rotationX; + public int rotationY; + public int rotationZ; + public int modelZoom; + public int animation; + public boolean orthogonal; + public int modelHeightOverride; + public int fontId; + public String text; + public int lineHeight; + public int xTextAlignment; + public int yTextAlignment; + public boolean textShadowed; + public int textColor; + public boolean filled; + public int lineWidth; + public boolean lineDirection; + public int clickMask; + public String name; + public String[] actions; + public int dragDeadZone; + public int dragDeadTime; + public boolean dragRenderBehavior; + public String targetVerb; + public Object[] onLoadListener; + public Object[] onMouseOverListener; + public Object[] onMouseLeaveListener; + public Object[] onTargetLeaveListener; + public Object[] onTargetEnterListener; + public Object[] onVarTransmitListener; + public Object[] onInvTransmitListener; + public Object[] onStatTransmitListener; + public Object[] onTimerListener; + public Object[] onOpListener; + public Object[] onMouseRepeatListener; + public Object[] onClickListener; + public Object[] onClickRepeatListener; + public Object[] onReleaseListener; + public Object[] onHoldListener; + public Object[] onDragListener; + public Object[] onDragCompleteListener; + public Object[] onScrollWheelListener; + public int[] varTransmitTriggers; + public int[] invTransmitTriggers; + public int[] statTransmitTriggers; + public boolean hasListener; + + public int menuType; + // This is set to a siblings' child id when that widget should get a hover effect when this one is hovered + public int hoveredSiblingId; + public int[] alternateOperators; + public int[] alternateRhs; + public ClientScript1Instruction[][] clientScripts; + public int[] itemIds; + public int[] itemQuantities; + public int xPitch; + public int yPitch; + public int[] xOffsets; + public int[] yOffsets; + public int[] sprites; + public String[] configActions; + public String alternateText; + public int alternateTextColor; + public int hoveredTextColor; + public int alternateHoveredTextColor; + public int alternateSpriteId; + public int alternateModelId; + public int alternateAnimation; + public String spellName; + public String tooltip; +} diff --git a/src/main/java/net/runelite/cache/definitions/InventoryDefinition.java b/src/main/java/net/runelite/cache/definitions/InventoryDefinition.java new file mode 100644 index 0000000..5239f5c --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/InventoryDefinition.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class InventoryDefinition +{ + public int id; + public int size; +} diff --git a/src/main/java/net/runelite/cache/definitions/ItemDefinition.java b/src/main/java/net/runelite/cache/definitions/ItemDefinition.java new file mode 100644 index 0000000..8f67622 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/ItemDefinition.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import java.util.Map; +import lombok.Data; + +@Data +public class ItemDefinition +{ + public final int id; + + public String name = "null"; + + public int resizeX = 128; + public int resizeY = 128; + public int resizeZ = 128; + + public int xan2d = 0; + public int yan2d = 0; + public int zan2d = 0; + + public int cost = 1; + public boolean isTradeable; + public int stackable = 0; + public int inventoryModel; + public boolean members = false; + + public short[] colorFind; + public short[] colorReplace; + public short[] textureFind; + public short[] textureReplace; + + public int zoom2d = 2000; + public int xOffset2d = 0; + public int yOffset2d = 0; + + public int ambient; + public int contrast; + + public int[] countCo; + public int[] countObj; + + public String[] options = new String[] + { + null, null, "Take", null, null + }; + + public String[] interfaceOptions = new String[] + { + null, null, null, null, "Drop" + }; + + public int maleModel0 = -1; + public int maleModel1 = -1; + public int maleModel2 = -1; + public int maleOffset; + public int maleHeadModel = -1; + public int maleHeadModel2 = -1; + + public int femaleModel0 = -1; + public int femaleModel1 = -1; + public int femaleModel2 = -1; + public int femaleOffset; + public int femaleHeadModel = -1; + public int femaleHeadModel2 = -1; + + public int notedID = -1; + public int notedTemplate = -1; + + public int team; + + public int shiftClickDropIndex = -2; + + public int boughtId = -1; + public int boughtTemplateId = -1; + + public int placeholderId = -1; + public int placeholderTemplateId = -1; + + public Map params = null; + + public void updateNote(ItemDefinition notedItem, ItemDefinition unnotedItem) + { + this.inventoryModel = notedItem.inventoryModel; + this.zoom2d = notedItem.zoom2d; + this.xan2d = notedItem.xan2d; + this.yan2d = notedItem.yan2d; + this.zan2d = notedItem.zan2d; + this.xOffset2d = notedItem.xOffset2d; + this.yOffset2d = notedItem.yOffset2d; + this.colorFind = notedItem.colorFind; + this.colorReplace = notedItem.colorReplace; + this.textureFind = notedItem.textureFind; + this.textureReplace = notedItem.textureReplace; + this.name = unnotedItem.name; + this.members = unnotedItem.members; + this.cost = unnotedItem.cost; + this.stackable = 1; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/KitDefinition.java b/src/main/java/net/runelite/cache/definitions/KitDefinition.java new file mode 100644 index 0000000..bd2ee53 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/KitDefinition.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class KitDefinition +{ + private final int id; + public short[] recolorToReplace; + public short[] recolorToFind; + public short[] retextureToFind; + public short[] retextureToReplace; + public int bodyPartId = -1; + public int[] modelIds; + public int[] models = new int[] + { + -1, -1, -1, -1, -1 + }; + public boolean nonSelectable = false; +} diff --git a/src/main/java/net/runelite/cache/definitions/LocationsDefinition.java b/src/main/java/net/runelite/cache/definitions/LocationsDefinition.java new file mode 100644 index 0000000..435cdd4 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/LocationsDefinition.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import java.util.ArrayList; +import java.util.List; +import lombok.Data; +import net.runelite.cache.region.Location; + +@Data +public class LocationsDefinition +{ + private int regionX; + private int regionY; + private List locations = new ArrayList<>(); +} diff --git a/src/main/java/net/runelite/cache/definitions/MapDefinition.java b/src/main/java/net/runelite/cache/definitions/MapDefinition.java new file mode 100644 index 0000000..b695b24 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/MapDefinition.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class MapDefinition +{ + public static final int X = 64; + public static final int Y = 64; + public static final int Z = 4; + + @Data + public static class Tile + { + public Integer height; + public int attrOpcode; + public byte settings; + public byte overlayId; + public byte overlayPath; + public byte overlayRotation; + public byte underlayId; + } + + private int regionX; + private int regionY; + private Tile[][][] tiles = new Tile[Z][X][Y]; +} diff --git a/src/main/java/net/runelite/cache/definitions/ModelDefinition.java b/src/main/java/net/runelite/cache/definitions/ModelDefinition.java new file mode 100644 index 0000000..2259026 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/ModelDefinition.java @@ -0,0 +1,635 @@ +package net.runelite.cache.definitions; + +import java.util.Arrays; +import lombok.Data; +import net.runelite.cache.models.CircularAngle; +import net.runelite.cache.models.FaceNormal; +import net.runelite.cache.models.VertexNormal; + +@Data +public class ModelDefinition +{ + public int id; + + public int vertexCount = 0; + public int[] vertexPositionsX; + public int[] vertexPositionsY; + public int[] vertexPositionsZ; + public transient VertexNormal[] vertexNormals; + + public int faceCount; + public int[] faceVertexIndices1; + public int[] faceVertexIndices2; + public int[] faceVertexIndices3; + public byte[] faceAlphas; + public short[] faceColors; + public byte[] faceRenderPriorities; + public byte[] faceRenderTypes; + public transient FaceNormal[] faceNormals; + + public int textureTriangleCount; + public short[] textureTriangleVertexIndices1; + public short[] textureTriangleVertexIndices2; + public short[] textureTriangleVertexIndices3; + public transient float[][] faceTextureUCoordinates; + public transient float[][] faceTextureVCoordinates; + public short[] texturePrimaryColors; + public short[] faceTextures; + public byte[] textureCoordinates; + public byte[] textureRenderTypes; + + public int[] vertexSkins; + public int[] faceSkins; + + public byte priority; + + public short[] aShortArray2574; + public short[] aShortArray2575; + public short[] aShortArray2577; + public short[] aShortArray2578; + public byte[] aByteArray2580; + public short[] aShortArray2586; + + private transient int[][] vertexGroups; + + private transient int[] origVX; + private transient int[] origVY; + private transient int[] origVZ; + + public transient int maxPriority; + + public static transient int animOffsetX, animOffsetY, animOffsetZ; + + public void computeNormals() + { + if (this.vertexNormals != null) + { + return; + } + + this.vertexNormals = new VertexNormal[this.vertexCount]; + + int var1; + for (var1 = 0; var1 < this.vertexCount; ++var1) + { + this.vertexNormals[var1] = new VertexNormal(); + } + + for (var1 = 0; var1 < this.faceCount; ++var1) + { + int vertexA = this.faceVertexIndices1[var1]; + int vertexB = this.faceVertexIndices2[var1]; + int vertexC = this.faceVertexIndices3[var1]; + + int xA = this.vertexPositionsX[vertexB] - this.vertexPositionsX[vertexA]; + int yA = this.vertexPositionsY[vertexB] - this.vertexPositionsY[vertexA]; + int zA = this.vertexPositionsZ[vertexB] - this.vertexPositionsZ[vertexA]; + + int xB = this.vertexPositionsX[vertexC] - this.vertexPositionsX[vertexA]; + int yB = this.vertexPositionsY[vertexC] - this.vertexPositionsY[vertexA]; + int zB = this.vertexPositionsZ[vertexC] - this.vertexPositionsZ[vertexA]; + + // Compute cross product + int var11 = yA * zB - yB * zA; + int var12 = zA * xB - zB * xA; + int var13 = xA * yB - xB * yA; + + while (var11 > 8192 || var12 > 8192 || var13 > 8192 || var11 < -8192 || var12 < -8192 || var13 < -8192) + { + var11 >>= 1; + var12 >>= 1; + var13 >>= 1; + } + + int length = (int) Math.sqrt((double) (var11 * var11 + var12 * var12 + var13 * var13)); + if (length <= 0) + { + length = 1; + } + + var11 = var11 * 256 / length; + var12 = var12 * 256 / length; + var13 = var13 * 256 / length; + + byte var15; + if (this.faceRenderTypes == null) + { + var15 = 0; + } + else + { + var15 = this.faceRenderTypes[var1]; + } + + if (var15 == 0) + { + VertexNormal var16 = this.vertexNormals[vertexA]; + var16.x += var11; + var16.y += var12; + var16.z += var13; + ++var16.magnitude; + + var16 = this.vertexNormals[vertexB]; + var16.x += var11; + var16.y += var12; + var16.z += var13; + ++var16.magnitude; + + var16 = this.vertexNormals[vertexC]; + var16.x += var11; + var16.y += var12; + var16.z += var13; + ++var16.magnitude; + } + else if (var15 == 1) + { + if (this.faceNormals == null) + { + this.faceNormals = new FaceNormal[this.faceCount]; + } + + FaceNormal var17 = this.faceNormals[var1] = new FaceNormal(); + var17.x = var11; + var17.y = var12; + var17.z = var13; + } + } + } + + /** + * Computes the UV coordinates for every three-vertex face that has a + * texture. + */ + public void computeTextureUVCoordinates() + { + this.faceTextureUCoordinates = new float[faceCount][]; + this.faceTextureVCoordinates = new float[faceCount][]; + + for (int i = 0; i < faceCount; i++) + { + int textureCoordinate; + if (textureCoordinates == null) + { + textureCoordinate = -1; + } + else + { + textureCoordinate = textureCoordinates[i]; + } + + int textureIdx; + if (faceTextures == null) + { + textureIdx = -1; + } + else + { + textureIdx = faceTextures[i] & 0xFFFF; + } + + if (textureIdx != -1) + { + float[] u = new float[3]; + float[] v = new float[3]; + + if (textureCoordinate == -1) + { + u[0] = 0.0F; + v[0] = 1.0F; + + u[1] = 1.0F; + v[1] = 1.0F; + + u[2] = 0.0F; + v[2] = 0.0F; + } + else + { + textureCoordinate &= 0xFF; + + byte textureRenderType = 0; + if (textureRenderTypes != null) + { + textureRenderType = textureRenderTypes[textureCoordinate]; + } + + if (textureRenderType == 0) + { + int faceVertexIdx1 = faceVertexIndices1[i]; + int faceVertexIdx2 = faceVertexIndices2[i]; + int faceVertexIdx3 = faceVertexIndices3[i]; + + short triangleVertexIdx1 = textureTriangleVertexIndices1[textureCoordinate]; + short triangleVertexIdx2 = textureTriangleVertexIndices2[textureCoordinate]; + short triangleVertexIdx3 = textureTriangleVertexIndices3[textureCoordinate]; + + float triangleX = (float) vertexPositionsX[triangleVertexIdx1]; + float triangleY = (float) vertexPositionsY[triangleVertexIdx1]; + float triangleZ = (float) vertexPositionsZ[triangleVertexIdx1]; + + float f_882_ = (float) vertexPositionsX[triangleVertexIdx2] - triangleX; + float f_883_ = (float) vertexPositionsY[triangleVertexIdx2] - triangleY; + float f_884_ = (float) vertexPositionsZ[triangleVertexIdx2] - triangleZ; + float f_885_ = (float) vertexPositionsX[triangleVertexIdx3] - triangleX; + float f_886_ = (float) vertexPositionsY[triangleVertexIdx3] - triangleY; + float f_887_ = (float) vertexPositionsZ[triangleVertexIdx3] - triangleZ; + float f_888_ = (float) vertexPositionsX[faceVertexIdx1] - triangleX; + float f_889_ = (float) vertexPositionsY[faceVertexIdx1] - triangleY; + float f_890_ = (float) vertexPositionsZ[faceVertexIdx1] - triangleZ; + float f_891_ = (float) vertexPositionsX[faceVertexIdx2] - triangleX; + float f_892_ = (float) vertexPositionsY[faceVertexIdx2] - triangleY; + float f_893_ = (float) vertexPositionsZ[faceVertexIdx2] - triangleZ; + float f_894_ = (float) vertexPositionsX[faceVertexIdx3] - triangleX; + float f_895_ = (float) vertexPositionsY[faceVertexIdx3] - triangleY; + float f_896_ = (float) vertexPositionsZ[faceVertexIdx3] - triangleZ; + + float f_897_ = f_883_ * f_887_ - f_884_ * f_886_; + float f_898_ = f_884_ * f_885_ - f_882_ * f_887_; + float f_899_ = f_882_ * f_886_ - f_883_ * f_885_; + float f_900_ = f_886_ * f_899_ - f_887_ * f_898_; + float f_901_ = f_887_ * f_897_ - f_885_ * f_899_; + float f_902_ = f_885_ * f_898_ - f_886_ * f_897_; + float f_903_ = 1.0F / (f_900_ * f_882_ + f_901_ * f_883_ + f_902_ * f_884_); + + u[0] = (f_900_ * f_888_ + f_901_ * f_889_ + f_902_ * f_890_) * f_903_; + u[1] = (f_900_ * f_891_ + f_901_ * f_892_ + f_902_ * f_893_) * f_903_; + u[2] = (f_900_ * f_894_ + f_901_ * f_895_ + f_902_ * f_896_) * f_903_; + + f_900_ = f_883_ * f_899_ - f_884_ * f_898_; + f_901_ = f_884_ * f_897_ - f_882_ * f_899_; + f_902_ = f_882_ * f_898_ - f_883_ * f_897_; + f_903_ = 1.0F / (f_900_ * f_885_ + f_901_ * f_886_ + f_902_ * f_887_); + + v[0] = (f_900_ * f_888_ + f_901_ * f_889_ + f_902_ * f_890_) * f_903_; + v[1] = (f_900_ * f_891_ + f_901_ * f_892_ + f_902_ * f_893_) * f_903_; + v[2] = (f_900_ * f_894_ + f_901_ * f_895_ + f_902_ * f_896_) * f_903_; + } + } + + this.faceTextureUCoordinates[i] = u; + this.faceTextureVCoordinates[i] = v; + } + } + } + + public void computeAnimationTables() + { + if (this.vertexSkins != null) + { + int[] groupCounts = new int[256]; + int numGroups = 0; + int var3, var4; + + for (var3 = 0; var3 < this.vertexCount; ++var3) + { + var4 = this.vertexSkins[var3]; + ++groupCounts[var4]; + if (var4 > numGroups) + { + numGroups = var4; + } + } + + this.vertexGroups = new int[numGroups + 1][]; + + for (var3 = 0; var3 <= numGroups; ++var3) + { + this.vertexGroups[var3] = new int[groupCounts[var3]]; + groupCounts[var3] = 0; + } + + for (var3 = 0; var3 < this.vertexCount; this.vertexGroups[var4][groupCounts[var4]++] = var3++) + { + var4 = this.vertexSkins[var3]; + } + + this.vertexSkins = null; + } + + // triangleSkinValues is here + } + + public void rotate(int orientation) + { + int sin = CircularAngle.SINE[orientation]; + int cos = CircularAngle.COSINE[orientation]; + + assert vertexPositionsX.length == vertexPositionsY.length; + assert vertexPositionsY.length == vertexPositionsZ.length; + + for (int i = 0; i < vertexPositionsX.length; ++i) + { + vertexPositionsX[i] = vertexPositionsX[i] * cos + vertexPositionsZ[i] * sin >> 16; + vertexPositionsZ[i] = vertexPositionsZ[i] * cos - vertexPositionsX[i] * sin >> 16; + } + + reset(); + } + + public void resetAnim() + { + if (origVX == null) + { + return; + } + + System.arraycopy(origVX, 0, vertexPositionsX, 0, origVX.length); + System.arraycopy(origVY, 0, vertexPositionsY, 0, origVY.length); + System.arraycopy(origVZ, 0, vertexPositionsZ, 0, origVZ.length); + } + + public void animate(int type, int[] frameMap, int dx, int dy, int dz) + { + if (origVX == null) + { + origVX = Arrays.copyOf(vertexPositionsX, vertexPositionsX.length); + origVY = Arrays.copyOf(vertexPositionsY, vertexPositionsY.length); + origVZ = Arrays.copyOf(vertexPositionsZ, vertexPositionsZ.length); + } + + final int[] verticesX = vertexPositionsX; + final int[] verticesY = vertexPositionsY; + final int[] verticesZ = vertexPositionsZ; + int var6 = frameMap.length; + int var7; + int var8; + int var11; + int var12; + if (type == 0) + { + var7 = 0; + animOffsetX = 0; + animOffsetY = 0; + animOffsetZ = 0; + + for (var8 = 0; var8 < var6; ++var8) + { + int var9 = frameMap[var8]; + if (var9 < this.vertexGroups.length) + { + int[] var10 = this.vertexGroups[var9]; + + for (var11 = 0; var11 < var10.length; ++var11) + { + var12 = var10[var11]; + animOffsetX += verticesX[var12]; + animOffsetY += verticesY[var12]; + animOffsetZ += verticesZ[var12]; + ++var7; + } + } + } + + if (var7 > 0) + { + animOffsetX = dx + animOffsetX / var7; + animOffsetY = dy + animOffsetY / var7; + animOffsetZ = dz + animOffsetZ / var7; + } + else + { + animOffsetX = dx; + animOffsetY = dy; + animOffsetZ = dz; + } + + } + else + { + int[] var18; + int var19; + if (type == 1) + { + for (var7 = 0; var7 < var6; ++var7) + { + var8 = frameMap[var7]; + if (var8 < this.vertexGroups.length) + { + var18 = this.vertexGroups[var8]; + + for (var19 = 0; var19 < var18.length; ++var19) + { + var11 = var18[var19]; + verticesX[var11] += dx; + verticesY[var11] += dy; + verticesZ[var11] += dz; + } + } + } + + } + else if (type == 2) + { + for (var7 = 0; var7 < var6; ++var7) + { + var8 = frameMap[var7]; + if (var8 < this.vertexGroups.length) + { + var18 = this.vertexGroups[var8]; + + for (var19 = 0; var19 < var18.length; ++var19) + { + var11 = var18[var19]; + verticesX[var11] -= animOffsetX; + verticesY[var11] -= animOffsetY; + verticesZ[var11] -= animOffsetZ; + var12 = (dx & 255) * 8; + int var13 = (dy & 255) * 8; + int var14 = (dz & 255) * 8; + int var15; + int var16; + int var17; + if (var14 != 0) + { + var15 = CircularAngle.SINE[var14]; + var16 = CircularAngle.COSINE[var14]; + var17 = var15 * verticesY[var11] + var16 * verticesX[var11] >> 16; + verticesY[var11] = var16 * verticesY[var11] - var15 * verticesX[var11] >> 16; + verticesX[var11] = var17; + } + + if (var12 != 0) + { + var15 = CircularAngle.SINE[var12]; + var16 = CircularAngle.COSINE[var12]; + var17 = var16 * verticesY[var11] - var15 * verticesZ[var11] >> 16; + verticesZ[var11] = var15 * verticesY[var11] + var16 * verticesZ[var11] >> 16; + verticesY[var11] = var17; + } + + if (var13 != 0) + { + var15 = CircularAngle.SINE[var13]; + var16 = CircularAngle.COSINE[var13]; + var17 = var15 * verticesZ[var11] + var16 * verticesX[var11] >> 16; + verticesZ[var11] = var16 * verticesZ[var11] - var15 * verticesX[var11] >> 16; + verticesX[var11] = var17; + } + + verticesX[var11] += animOffsetX; + verticesY[var11] += animOffsetY; + verticesZ[var11] += animOffsetZ; + } + } + } + + } + else if (type == 3) + { + for (var7 = 0; var7 < var6; ++var7) + { + var8 = frameMap[var7]; + if (var8 < this.vertexGroups.length) + { + var18 = this.vertexGroups[var8]; + + for (var19 = 0; var19 < var18.length; ++var19) + { + var11 = var18[var19]; + verticesX[var11] -= animOffsetX; + verticesY[var11] -= animOffsetY; + verticesZ[var11] -= animOffsetZ; + verticesX[var11] = dx * verticesX[var11] / 128; + verticesY[var11] = dy * verticesY[var11] / 128; + verticesZ[var11] = dz * verticesZ[var11] / 128; + verticesX[var11] += animOffsetX; + verticesY[var11] += animOffsetY; + verticesZ[var11] += animOffsetZ; + } + } + } + + } + else if (type == 5) + { + // alpha animation + } + } + } + + public void method1493() + { + int var1; + for (var1 = 0; var1 < this.vertexCount; ++var1) + { + this.vertexPositionsZ[var1] = -this.vertexPositionsZ[var1]; + } + + for (var1 = 0; var1 < this.faceCount; ++var1) + { + int var2 = this.faceVertexIndices1[var1]; + this.faceVertexIndices1[var1] = this.faceVertexIndices3[var1]; + this.faceVertexIndices3[var1] = var2; + } + + reset(); + } + + public void rotate1() + { + for (int var1 = 0; var1 < this.vertexCount; ++var1) + { + int var2 = this.vertexPositionsX[var1]; + this.vertexPositionsX[var1] = this.vertexPositionsZ[var1]; + this.vertexPositionsZ[var1] = -var2; + } + + reset(); + } + + public void rotate2() + { + for (int var1 = 0; var1 < this.vertexCount; ++var1) + { + this.vertexPositionsX[var1] = -this.vertexPositionsX[var1]; + this.vertexPositionsZ[var1] = -this.vertexPositionsZ[var1]; + } + + reset(); + } + + public void rotate3() + { + for (int var1 = 0; var1 < this.vertexCount; ++var1) + { + int var2 = this.vertexPositionsZ[var1]; + this.vertexPositionsZ[var1] = this.vertexPositionsX[var1]; + this.vertexPositionsX[var1] = -var2; + } + + reset(); + } + + private void reset() + { + vertexNormals = null; + faceNormals = null; + faceTextureUCoordinates = faceTextureVCoordinates = null; + } + + public void resize(int var1, int var2, int var3) + { + for (int var4 = 0; var4 < this.vertexCount; ++var4) + { + this.vertexPositionsX[var4] = this.vertexPositionsX[var4] * var1 / 128; + this.vertexPositionsY[var4] = var2 * this.vertexPositionsY[var4] / 128; + this.vertexPositionsZ[var4] = var3 * this.vertexPositionsZ[var4] / 128; + } + + reset(); + } + + public void recolor(short var1, short var2) + { + for (int var3 = 0; var3 < this.faceCount; ++var3) + { + if (this.faceColors[var3] == var1) + { + this.faceColors[var3] = var2; + } + } + + } + + public void retexture(short var1, short var2) + { + if (this.faceTextures != null) + { + for (int var3 = 0; var3 < this.faceCount; ++var3) + { + if (this.faceTextures[var3] == var1) + { + this.faceTextures[var3] = var2; + } + } + + } + } + + public void move(int xOffset, int yOffset, int zOffset) + { + for (int i = 0; i < this.vertexCount; i++) + { + this.vertexPositionsX[i] += xOffset; + this.vertexPositionsY[i] += yOffset; + this.vertexPositionsZ[i] += zOffset; + } + this.reset(); + } + + public void computeMaxPriority() + { + if (faceRenderPriorities == null) + { + return; + } + + for (int i = 0; i < faceCount; ++i) + { + if (faceRenderPriorities[i] > maxPriority) + { + maxPriority = faceRenderPriorities[i]; + } + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/NpcDefinition.java b/src/main/java/net/runelite/cache/definitions/NpcDefinition.java new file mode 100644 index 0000000..ddfabfe --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/NpcDefinition.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.definitions; + +import java.util.Map; +import lombok.Data; + +@Data +public class NpcDefinition +{ + public final int id; + public String name = "null"; + public int size = 1; + public int[] models; + public int[] chatheadModels; + public int standingAnimation = -1; + public int rotateLeftAnimation = -1; + public int rotateRightAnimation = -1; + public int walkingAnimation = -1; + public int rotate180Animation = -1; + public int rotate90RightAnimation = -1; + public int rotate90LeftAnimation = -1; + public short[] recolorToFind; + public short[] recolorToReplace; + public short[] retextureToFind; + public short[] retextureToReplace; + public String[] actions = new String[5]; + public boolean isMinimapVisible = true; + public int combatLevel = -1; + public int widthScale = 128; + public int heightScale = 128; + public boolean hasRenderPriority; + public int ambient; + public int contrast; + public int headIcon = -1; + public int rotationSpeed = 32; + public int[] configs; + public int varbitId = -1; + public int varpIndex = -1; + public boolean isInteractable = true; + public boolean rotationFlag = true; + public boolean isPet; + public Map params; +} diff --git a/src/main/java/net/runelite/cache/definitions/ObjectDefinition.java b/src/main/java/net/runelite/cache/definitions/ObjectDefinition.java new file mode 100644 index 0000000..473a9d6 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/ObjectDefinition.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.definitions; + +import java.util.Map; +import lombok.Data; + +@Data +public class ObjectDefinition +{ + private int id; + private short[] retextureToFind; + private int decorDisplacement = 16; + private boolean isHollow = false; + private String name = "null"; + private int[] objectModels; + private int[] objectTypes; + private short[] recolorToFind; + private int mapAreaId = -1; + private short[] textureToReplace; + private int sizeX = 1; + private int sizeY = 1; + private int anInt2083 = 0; + private int[] anIntArray2084; + private int offsetX = 0; + private boolean mergeNormals = false; + private int wallOrDoor = -1; + private int animationID = -1; + private int varbitID = -1; + private int ambient = 0; + private int contrast = 0; + private String[] actions = new String[5]; + private int interactType = 2; + private int mapSceneID = -1; + private short[] recolorToReplace; + private boolean shadow = true; + private int modelSizeX = 128; + private int modelSizeHeight = 128; + private int modelSizeY = 128; + private int objectID; + private int offsetHeight = 0; + private int offsetY = 0; + private boolean obstructsGround = false; + private int contouredGround = -1; + private int supportsItems = -1; + private int[] configChangeDest; + private boolean isRotated = false; + private int varpID = -1; + private int ambientSoundId = -1; + private boolean aBool2111 = false; + private int anInt2112 = 0; + private int anInt2113 = 0; + private boolean blocksProjectile = true; + private Map params = null; +} diff --git a/src/main/java/net/runelite/cache/definitions/OverlayDefinition.java b/src/main/java/net/runelite/cache/definitions/OverlayDefinition.java new file mode 100644 index 0000000..3846e99 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/OverlayDefinition.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class OverlayDefinition +{ + private int id; + private int rgbColor = 0; + private int texture = -1; + private int secondaryRgbColor = -1; + private boolean hideUnderlay = true; + + private transient int hue; + private transient int saturation; + private transient int lightness; + + private transient int otherHue; + private transient int otherSaturation; + private transient int otherLightness; + + public void calculateHsl() + { + if (secondaryRgbColor != -1) + { + calculateHsl(secondaryRgbColor); + otherHue = hue; + otherSaturation = saturation; + otherLightness = lightness; + } + + calculateHsl(rgbColor); + } + + private void calculateHsl(int var1) + { + double var2 = (double) (var1 >> 16 & 255) / 256.0D; + double var4 = (double) (var1 >> 8 & 255) / 256.0D; + double var6 = (double) (var1 & 255) / 256.0D; + double var8 = var2; + if (var4 < var2) + { + var8 = var4; + } + + if (var6 < var8) + { + var8 = var6; + } + + double var10 = var2; + if (var4 > var2) + { + var10 = var4; + } + + if (var6 > var10) + { + var10 = var6; + } + + double var12 = 0.0D; + double var14 = 0.0D; + double var16 = (var8 + var10) / 2.0D; + if (var10 != var8) + { + if (var16 < 0.5D) + { + var14 = (var10 - var8) / (var10 + var8); + } + + if (var16 >= 0.5D) + { + var14 = (var10 - var8) / (2.0D - var10 - var8); + } + + if (var2 == var10) + { + var12 = (var4 - var6) / (var10 - var8); + } + else if (var4 == var10) + { + var12 = 2.0D + (var6 - var2) / (var10 - var8); + } + else if (var10 == var6) + { + var12 = 4.0D + (var2 - var4) / (var10 - var8); + } + } + + var12 /= 6.0D; + this.hue = (int) (256.0D * var12); + this.saturation = (int) (var14 * 256.0D); + this.lightness = (int) (var16 * 256.0D); + if (this.saturation < 0) + { + this.saturation = 0; + } + else if (this.saturation > 255) + { + this.saturation = 255; + } + + if (this.lightness < 0) + { + this.lightness = 0; + } + else if (this.lightness > 255) + { + this.lightness = 255; + } + + } +} diff --git a/src/main/java/net/runelite/cache/definitions/ParamDefinition.java b/src/main/java/net/runelite/cache/definitions/ParamDefinition.java new file mode 100644 index 0000000..c3a25a1 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/ParamDefinition.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; +import net.runelite.cache.util.ScriptVarType; + +@Data +public class ParamDefinition +{ + private ScriptVarType type; + private boolean isMembers = true; + private int defaultInt; + private String defaultString; +} diff --git a/src/main/java/net/runelite/cache/definitions/ScriptDefinition.java b/src/main/java/net/runelite/cache/definitions/ScriptDefinition.java new file mode 100644 index 0000000..cb57851 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/ScriptDefinition.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import java.util.Map; +import lombok.Data; + +@Data +public class ScriptDefinition +{ + private int id; + private int[] instructions; + private int[] intOperands; + private String[] stringOperands; + private int intStackCount; + private int stringStackCount; + private int localIntCount; + private int localStringCount; + private Map[] switches; +} diff --git a/src/main/java/net/runelite/cache/definitions/SequenceDefinition.java b/src/main/java/net/runelite/cache/definitions/SequenceDefinition.java new file mode 100644 index 0000000..3f280f3 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/SequenceDefinition.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class SequenceDefinition +{ + private final int id; + public int[] frameIDs; // top 16 bits are FrameDefinition ids + public int[] field3048; + public int[] frameLenghts; + public int rightHandItem = -1; + public int[] interleaveLeave; + public boolean stretches = false; + public int forcedPriority = 5; + public int maxLoops = 99; + public int[] field3056; + public int precedenceAnimating = -1; + public int leftHandItem = -1; + public int replyMode = 2; + public int frameStep = -1; + public int priority = -1; +} diff --git a/src/main/java/net/runelite/cache/definitions/SpotAnimDefinition.java b/src/main/java/net/runelite/cache/definitions/SpotAnimDefinition.java new file mode 100644 index 0000000..e85b391 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/SpotAnimDefinition.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class SpotAnimDefinition +{ + public int rotaton = 0; + public short[] textureToReplace; + public int id; + public short[] textureToFind; + public int resizeY = 128; + public int animationId = -1; + public short[] recolorToFind; + public short[] recolorToReplace; + public int resizeX = 128; + public int modelId; + public int ambient = 0; + public int contrast = 0; +} diff --git a/src/main/java/net/runelite/cache/definitions/SpriteDefinition.java b/src/main/java/net/runelite/cache/definitions/SpriteDefinition.java new file mode 100644 index 0000000..632ea1e --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/SpriteDefinition.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class SpriteDefinition +{ + private int id; + private int frame; + private int offsetX; + private int offsetY; + private int width; + private int height; + private int[] pixels; + private int maxWidth; + private int maxHeight; + + public transient byte[] pixelIdx; + public transient int[] palette; + + public void normalize() + { + if (this.width != this.maxWidth || this.height != this.maxHeight) + { + byte[] var1 = new byte[this.maxWidth * this.maxHeight]; + int var2 = 0; + + for (int var3 = 0; var3 < this.height; ++var3) + { + for (int var4 = 0; var4 < this.width; ++var4) + { + var1[var4 + (var3 + this.offsetY) * this.maxWidth + this.offsetX] = this.pixelIdx[var2++]; + } + } + + this.pixelIdx = var1; + this.width = this.maxWidth; + this.height = this.maxHeight; + this.offsetX = 0; + this.offsetY = 0; + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/StructDefinition.java b/src/main/java/net/runelite/cache/definitions/StructDefinition.java new file mode 100644 index 0000000..455ce9e --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/StructDefinition.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018, Joshua Filby + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import java.util.Map; +import lombok.Data; + +@Data +public class StructDefinition +{ + public final int id; + public Map params = null; +} diff --git a/src/main/java/net/runelite/cache/definitions/TextureDefinition.java b/src/main/java/net/runelite/cache/definitions/TextureDefinition.java new file mode 100644 index 0000000..d34bc56 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/TextureDefinition.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.definitions; + +import lombok.Data; +import net.runelite.cache.definitions.providers.SpriteProvider; + +@Data +public class TextureDefinition +{ + public int field1777; + public boolean field1778; + private int id; + private int[] fileIds; + public int[] field1780; + public int[] field1781; + public int[] field1786; + public int field1782; + public int field1783; + + public transient int[] pixels; + + public boolean method2680(double var1, int var3, SpriteProvider spriteProvider) + { + int var5 = var3 * var3; + this.pixels = new int[var5]; + + for (int var6 = 0; var6 < this.fileIds.length; ++var6) + { + SpriteDefinition var7 = spriteProvider.provide(fileIds[var6], 0); + var7.normalize(); + byte[] var8 = var7.pixelIdx; + int[] var9 = var7.palette; + int var10 = this.field1786[var6]; + + int var11; + int var12; + int var13; + int var14; + if ((var10 & -16777216) == 50331648) + { + var11 = var10 & 16711935; + var12 = var10 >> 8 & 255; + + for (var13 = 0; var13 < var9.length; ++var13) + { + var14 = var9[var13]; + if (var14 >> 8 == (var14 & 65535)) + { + var14 &= 255; + var9[var13] = var11 * var14 >> 8 & 16711935 | var12 * var14 & 65280; + } + } + } + + for (var11 = 0; var11 < var9.length; ++var11) + { + var9[var11] = adjustRGB(var9[var11], var1); + } + + if (var6 == 0) + { + var11 = 0; + } + else + { + var11 = this.field1780[var6 - 1]; + } + + if (var11 == 0) + { + if (var3 == var7.getMaxWidth()) + { + for (var12 = 0; var12 < var5; ++var12) + { + this.pixels[var12] = var9[var8[var12] & 255]; + } + } + else if (var7.getMaxWidth() == 64 && var3 == 128) + { + var12 = 0; + + for (var13 = 0; var13 < var3; ++var13) + { + for (var14 = 0; var14 < var3; ++var14) + { + this.pixels[var12++] = var9[var8[(var13 >> 1 << 6) + (var14 >> 1)] & 255]; + } + } + } + else + { + if (var7.getMaxWidth() != 128 || var3 != 64) + { + throw new RuntimeException(); + } + + var12 = 0; + + for (var13 = 0; var13 < var3; ++var13) + { + for (var14 = 0; var14 < var3; ++var14) + { + this.pixels[var12++] = var9[var8[(var14 << 1) + (var13 << 1 << 7)] & 255]; + } + } + } + } + } + + return true; + } + + static int adjustRGB(int var0, double var1) + { + double var3 = (double) (var0 >> 16) / 256.0D; + double var5 = (double) (var0 >> 8 & 255) / 256.0D; + double var7 = (double) (var0 & 255) / 256.0D; + var3 = Math.pow(var3, var1); + var5 = Math.pow(var5, var1); + var7 = Math.pow(var7, var1); + int var9 = (int) (var3 * 256.0D); + int var10 = (int) (var5 * 256.0D); + int var11 = (int) (var7 * 256.0D); + return var11 + (var10 << 8) + (var9 << 16); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/TrackDefinition.java b/src/main/java/net/runelite/cache/definitions/TrackDefinition.java new file mode 100644 index 0000000..136070e --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/TrackDefinition.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class TrackDefinition +{ + public byte[] midi; // midi file contents +} diff --git a/src/main/java/net/runelite/cache/definitions/UnderlayDefinition.java b/src/main/java/net/runelite/cache/definitions/UnderlayDefinition.java new file mode 100644 index 0000000..7d3d8c2 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/UnderlayDefinition.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class UnderlayDefinition +{ + private int id; + private int color; + + private transient int hue; + private transient int saturation; + private transient int lightness; + private transient int hueMultiplier; + + public void calculateHsl() + { + int var1 = color; + double var2 = (double) (var1 >> 16 & 255) / 256.0D; + double var4 = (double) (var1 >> 8 & 255) / 256.0D; + double var6 = (double) (var1 & 255) / 256.0D; + double var8 = var2; + if (var4 < var2) + { + var8 = var4; + } + + if (var6 < var8) + { + var8 = var6; + } + + double var10 = var2; + if (var4 > var2) + { + var10 = var4; + } + + if (var6 > var10) + { + var10 = var6; + } + + double var12 = 0.0D; + double var14 = 0.0D; + double var16 = (var10 + var8) / 2.0D; + if (var8 != var10) + { + if (var16 < 0.5D) + { + var14 = (var10 - var8) / (var8 + var10); + } + + if (var16 >= 0.5D) + { + var14 = (var10 - var8) / (2.0D - var10 - var8); + } + + if (var2 == var10) + { + var12 = (var4 - var6) / (var10 - var8); + } + else if (var10 == var4) + { + var12 = 2.0D + (var6 - var2) / (var10 - var8); + } + else if (var10 == var6) + { + var12 = 4.0D + (var2 - var4) / (var10 - var8); + } + } + + var12 /= 6.0D; + this.saturation = (int) (var14 * 256.0D); + this.lightness = (int) (var16 * 256.0D); + if (this.saturation < 0) + { + this.saturation = 0; + } + else if (this.saturation > 255) + { + this.saturation = 255; + } + + if (this.lightness < 0) + { + this.lightness = 0; + } + else if (this.lightness > 255) + { + this.lightness = 255; + } + + if (var16 > 0.5D) + { + this.hueMultiplier = (int) (var14 * (1.0D - var16) * 512.0D); + } + else + { + this.hueMultiplier = (int) (var14 * var16 * 512.0D); + } + + if (this.hueMultiplier < 1) + { + this.hueMultiplier = 1; + } + + this.hue = (int) ((double) this.hueMultiplier * var12); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/VarbitDefinition.java b/src/main/java/net/runelite/cache/definitions/VarbitDefinition.java new file mode 100644 index 0000000..f50ae2d --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/VarbitDefinition.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class VarbitDefinition +{ + private int id; + private int index; + private int leastSignificantBit; + private int mostSignificantBit; +} diff --git a/src/main/java/net/runelite/cache/definitions/WorldMapDefinition.java b/src/main/java/net/runelite/cache/definitions/WorldMapDefinition.java new file mode 100644 index 0000000..a833326 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/WorldMapDefinition.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import java.util.List; +import lombok.Data; +import net.runelite.cache.region.Position; + +@Data +public class WorldMapDefinition +{ + public String name; + public int field450; + public int field451; + public int fileId; + public int field453; + public int field454; + public int field456; + public boolean field457; + public List field458; + public String safeName; + public Position position; + public int field463; +} diff --git a/src/main/java/net/runelite/cache/definitions/WorldMapType0.java b/src/main/java/net/runelite/cache/definitions/WorldMapType0.java new file mode 100644 index 0000000..1294d0e --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/WorldMapType0.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class WorldMapType0 implements WorldMapTypeBase +{ + public int field600; + public int field601; + public int field602; + public int field603; + public int field604; + public int field605; + public int field606; + public int field607; + public int field608; + public int field609; +} diff --git a/src/main/java/net/runelite/cache/definitions/WorldMapType1.java b/src/main/java/net/runelite/cache/definitions/WorldMapType1.java new file mode 100644 index 0000000..15a4f3e --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/WorldMapType1.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class WorldMapType1 implements WorldMapTypeBase +{ + public int field424; + public int field425; + public int field426; + public int field427; + public int field428; + public int field429; + public int field431; + public int field433; + public int field434; + public int field435; +} diff --git a/src/main/java/net/runelite/cache/definitions/WorldMapType2.java b/src/main/java/net/runelite/cache/definitions/WorldMapType2.java new file mode 100644 index 0000000..7b53268 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/WorldMapType2.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class WorldMapType2 implements WorldMapTypeBase +{ + public int field510; + public int field511; + public int field512; + public int field514; + public int field515; + public int field519; +} diff --git a/src/main/java/net/runelite/cache/definitions/WorldMapType3.java b/src/main/java/net/runelite/cache/definitions/WorldMapType3.java new file mode 100644 index 0000000..433c8a1 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/WorldMapType3.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class WorldMapType3 implements WorldMapTypeBase +{ + public int field376; + public int field377; + public int field378; + public int field379; + public int field380; + public int field381; + public int field382; + public int field383; + public int field384; + public int field385; + public int field386; + public int field387; + public int field388; + public int field389; +} diff --git a/src/main/java/net/runelite/cache/definitions/WorldMapTypeBase.java b/src/main/java/net/runelite/cache/definitions/WorldMapTypeBase.java new file mode 100644 index 0000000..3e5229f --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/WorldMapTypeBase.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +public interface WorldMapTypeBase {} diff --git a/src/main/java/net/runelite/cache/definitions/exporters/InterfaceExporter.java b/src/main/java/net/runelite/cache/definitions/exporters/InterfaceExporter.java new file mode 100644 index 0000000..b1020b9 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/exporters/InterfaceExporter.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.exporters; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import net.runelite.cache.definitions.InterfaceDefinition; + +public class InterfaceExporter +{ + private final InterfaceDefinition item; + private final Gson gson; + + public InterfaceExporter(InterfaceDefinition item) + { + this.item = item; + + GsonBuilder builder = new GsonBuilder() + .setPrettyPrinting(); + gson = builder.create(); + } + + public String export() + { + return gson.toJson(item); + } + + public void exportTo(File file) throws IOException + { + try (FileWriter fw = new FileWriter(file)) + { + fw.write(export()); + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/exporters/ItemExporter.java b/src/main/java/net/runelite/cache/definitions/exporters/ItemExporter.java new file mode 100644 index 0000000..5dddff9 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/exporters/ItemExporter.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.exporters; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import net.runelite.cache.definitions.ItemDefinition; + +public class ItemExporter +{ + private final ItemDefinition item; + private final Gson gson; + + public ItemExporter(ItemDefinition item) + { + this.item = item; + + GsonBuilder builder = new GsonBuilder() + .setPrettyPrinting(); + gson = builder.create(); + } + + public String export() + { + return gson.toJson(item); + } + + public void exportTo(File file) throws IOException + { + try (FileWriter fw = new FileWriter(file)) + { + fw.write(export()); + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/exporters/NpcExporter.java b/src/main/java/net/runelite/cache/definitions/exporters/NpcExporter.java new file mode 100644 index 0000000..eec1be3 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/exporters/NpcExporter.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.exporters; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import net.runelite.cache.definitions.NpcDefinition; + +public class NpcExporter +{ + private final NpcDefinition npc; + private final Gson gson; + + public NpcExporter(NpcDefinition npc) + { + this.npc = npc; + + GsonBuilder builder = new GsonBuilder() + .setPrettyPrinting(); + gson = builder.create(); + } + + public String export() + { + return gson.toJson(npc); + } + + public void exportTo(File file) throws IOException + { + try (FileWriter fw = new FileWriter(file)) + { + fw.write(export()); + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/exporters/ObjectExporter.java b/src/main/java/net/runelite/cache/definitions/exporters/ObjectExporter.java new file mode 100644 index 0000000..994bff6 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/exporters/ObjectExporter.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.exporters; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import net.runelite.cache.definitions.ObjectDefinition; + +public class ObjectExporter +{ + private final ObjectDefinition object; + private final Gson gson; + + public ObjectExporter(ObjectDefinition object) + { + this.object = object; + + GsonBuilder builder = new GsonBuilder() + .setPrettyPrinting(); + gson = builder.create(); + } + + public String export() + { + return gson.toJson(object); + } + + public void exportTo(File file) throws IOException + { + try (FileWriter fw = new FileWriter(file)) + { + fw.write(export()); + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/exporters/SpriteExporter.java b/src/main/java/net/runelite/cache/definitions/exporters/SpriteExporter.java new file mode 100644 index 0000000..9c073d5 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/exporters/SpriteExporter.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.exporters; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; +import net.runelite.cache.definitions.SpriteDefinition; + +public class SpriteExporter +{ + private final SpriteDefinition sprite; + + public SpriteExporter(SpriteDefinition sprite) + { + this.sprite = sprite; + } + + public BufferedImage export() + { + BufferedImage bi = new BufferedImage(sprite.getWidth(), sprite.getHeight(), BufferedImage.TYPE_INT_ARGB); + bi.setRGB(0, 0, sprite.getWidth(), sprite.getHeight(), sprite.getPixels(), 0, sprite.getWidth()); + return bi; + } + + public void exportTo(File file) throws IOException + { + BufferedImage image = export(); + ImageIO.write(image, "png", file); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/AreaLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/AreaLoader.java new file mode 100644 index 0000000..7b47358 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/AreaLoader.java @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.AreaDefinition; +import net.runelite.cache.io.InputStream; + +public class AreaLoader +{ + public AreaDefinition load(byte[] b, int id) + { + InputStream in = new InputStream(b); + AreaDefinition def = new AreaDefinition(); + def.id = id; + + for (;;) + { + int opcode = in.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + processOpcode(def, in, opcode); + } + + return def; + } + + private void processOpcode(AreaDefinition def, InputStream in, int opcode) + { + if (opcode == 1) + { + def.spriteId = in.readBigSmart2(); + } + else if (opcode == 2) + { + def.field3294 = in.readBigSmart2(); + } + else if (opcode == 3) + { + def.name = in.readString(); + } + else if (opcode == 4) + { + def.field3296 = in.read24BitInt(); + } + else if (opcode == 5) + { + in.read24BitInt(); + } + else if (opcode == 6) + { + def.field3310 = in.readUnsignedByte(); + } + else if (opcode == 7) + { + int var3 = in.readUnsignedByte(); + if ((var3 & 1) == 0) + { + ; + } + + if ((var3 & 2) == 2) + { + ; + } + } + else if (opcode == 8) + { + in.readUnsignedByte(); + } + else if (opcode >= 10 && opcode <= 14) + { + def.field3298[opcode - 10] = in.readString(); + } + else if (opcode == 15) + { + int var3 = in.readUnsignedByte(); + def.field3300 = new int[var3 * 2]; + + int var4; + for (var4 = 0; var4 < var3 * 2; ++var4) + { + def.field3300[var4] = in.readShort(); + } + + in.readInt(); + var4 = in.readUnsignedByte(); + def.field3292 = new int[var4]; + + int var5; + for (var5 = 0; var5 < def.field3292.length; ++var5) + { + def.field3292[var5] = in.readInt(); + } + + def.field3309 = new byte[var3]; + + for (var5 = 0; var5 < var3; ++var5) + { + def.field3309[var5] = in.readByte(); + } + } + else if (opcode == 16) + { + + } + else if (opcode == 17) + { + def.field3308 = in.readString(); + } + else if (opcode == 18) + { + in.readBigSmart2(); + } + else if (opcode == 19) + { + def.field3297 = in.readUnsignedShort(); + } + else if (opcode == 21) + { + in.readInt(); + } + else if (opcode == 22) + { + in.readInt(); + } + else if (opcode == 23) + { + in.readUnsignedByte(); + in.readUnsignedByte(); + in.readUnsignedByte(); + } + else if (opcode == 24) + { + in.readShort(); + in.readShort(); + } + else if (opcode == 25) + { + in.readBigSmart2(); + } + else if (opcode == 28) + { + in.readUnsignedByte(); + } + else if (opcode == 29) + { + in.skip(1); +// class257[] var6 = new class257[] +// { +// class257.field3538, class257.field3539, class257.field3540 +// }; +// this.field3299 = (class257) Item.method1751(var6, var1.readUnsignedByte()); + } + else if (opcode == 30) + { + in.skip(1); +// class239[] var7 = new class239[] +// { +// class239.field3273, class239.field3275, class239.field3271 +// }; +// this.field3306 = (class239) Item.method1751(var7, var1.readUnsignedByte()); + } + + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/EnumLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/EnumLoader.java new file mode 100644 index 0000000..83542c4 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/EnumLoader.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.EnumDefinition; +import net.runelite.cache.io.InputStream; +import net.runelite.cache.util.ScriptVarType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EnumLoader +{ + private static final Logger logger = LoggerFactory.getLogger(EnumLoader.class); + + public EnumDefinition load(int id, byte[] b) + { + if (b.length == 1 && b[0] == 0) + { + return null; + } + + EnumDefinition def = new EnumDefinition(); + InputStream is = new InputStream(b); + + def.setId(id); + + for (;;) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + processOp(opcode, def, is); + } + + return def; + } + + private void processOp(int opcode, EnumDefinition def, InputStream is) + { + switch (opcode) + { + case 1: + def.setKeyType(ScriptVarType.forCharKey((char) is.readUnsignedByte())); + break; + case 2: + def.setValType(ScriptVarType.forCharKey((char) is.readUnsignedByte())); + break; + case 3: + def.setDefaultString(is.readString()); + break; + case 4: + def.setDefaultInt(is.readInt()); + break; + case 5: + { + int size = is.readUnsignedShort(); + int[] keys = new int[size]; + String[] stringVals = new String[size]; + for (int index = 0; index < size; ++index) + { + keys[index] = is.readInt(); + stringVals[index] = is.readString(); + } + def.setSize(size); + def.setKeys(keys); + def.setStringVals(stringVals); + break; + } + case 6: + { + int size = is.readUnsignedShort(); + int[] keys = new int[size]; + int[] intVals = new int[size]; + for (int index = 0; index < size; ++index) + { + keys[index] = is.readInt(); + intVals[index] = is.readInt(); + } + def.setSize(size); + def.setKeys(keys); + def.setIntVals(intVals); + break; + } + default: + logger.warn("Unrecognized opcode {}", opcode); + break; + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/FrameLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/FrameLoader.java new file mode 100644 index 0000000..5ec512d --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/FrameLoader.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.FrameDefinition; +import net.runelite.cache.definitions.FramemapDefinition; +import net.runelite.cache.io.InputStream; + +public class FrameLoader +{ + public FrameDefinition load(FramemapDefinition framemap, int id, byte[] b) + { + FrameDefinition def = new FrameDefinition(); + InputStream in = new InputStream(b); + InputStream data = new InputStream(b); + + def.id = id; + def.framemap = framemap; + + int framemapArchiveIndex = in.readUnsignedShort(); + int length = in.readUnsignedByte(); + + data.skip(3 + length); // framemapArchiveIndex + length + data + + int[] indexFrameIds = new int[500]; + int[] scratchTranslatorX = new int[500]; + int[] scratchTranslatorY = new int[500]; + int[] scratchTranslatorZ = new int[500]; + + int lastI = -1; + int index = 0; + for (int i = 0; i < length; ++i) + { + int var9 = in.readUnsignedByte(); + + if (var9 <= 0) + { + continue; + } + + if (def.framemap.types[i] != 0) + { + for (int var10 = i - 1; var10 > lastI; --var10) + { + if (def.framemap.types[var10] == 0) + { + indexFrameIds[index] = var10; + scratchTranslatorX[index] = 0; + scratchTranslatorY[index] = 0; + scratchTranslatorZ[index] = 0; + ++index; + break; + } + } + } + + indexFrameIds[index] = i; + short var11 = 0; + if (def.framemap.types[i] == 3) + { + var11 = 128; + } + + if ((var9 & 1) != 0) + { + scratchTranslatorX[index] = data.readShortSmart(); + } + else + { + scratchTranslatorX[index] = var11; + } + + if ((var9 & 2) != 0) + { + scratchTranslatorY[index] = data.readShortSmart(); + } + else + { + scratchTranslatorY[index] = var11; + } + + if ((var9 & 4) != 0) + { + scratchTranslatorZ[index] = data.readShortSmart(); + } + else + { + scratchTranslatorZ[index] = var11; + } + + lastI = i; + ++index; + if (def.framemap.types[i] == 5) + { + def.showing = true; + } + } + + if (data.getOffset() != b.length) + { + throw new RuntimeException(); + } + + def.translatorCount = index; + def.indexFrameIds = new int[index]; + def.translator_x = new int[index]; + def.translator_y = new int[index]; + def.translator_z = new int[index]; + + for (int i = 0; i < index; ++i) + { + def.indexFrameIds[i] = indexFrameIds[i]; + def.translator_x[i] = scratchTranslatorX[i]; + def.translator_y[i] = scratchTranslatorY[i]; + def.translator_z[i] = scratchTranslatorZ[i]; + } + + return def; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/FramemapLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/FramemapLoader.java new file mode 100644 index 0000000..b649af8 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/FramemapLoader.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.FramemapDefinition; +import net.runelite.cache.io.InputStream; + +public class FramemapLoader +{ + public FramemapDefinition load(int id, byte[] b) + { + FramemapDefinition def = new FramemapDefinition(); + InputStream in = new InputStream(b); + + def.id = id; + + def.length = in.readUnsignedByte(); + def.types = new int[def.length]; + def.frameMaps = new int[def.length][]; + + for (int i = 0; i < def.length; ++i) + { + def.types[i] = in.readUnsignedByte(); + } + + for (int i = 0; i < def.length; ++i) + { + def.frameMaps[i] = new int[in.readUnsignedByte()]; + } + + for (int i = 0; i < def.length; ++i) + { + for (int j = 0; j < def.frameMaps[i].length; ++j) + { + def.frameMaps[i][j] = in.readUnsignedByte(); + } + } + + return def; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/InterfaceLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/InterfaceLoader.java new file mode 100644 index 0000000..69db420 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/InterfaceLoader.java @@ -0,0 +1,572 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import net.runelite.cache.definitions.ClientScript1Instruction; +import net.runelite.cache.definitions.InterfaceDefinition; +import net.runelite.cache.io.InputStream; + +public class InterfaceLoader +{ + public InterfaceDefinition load(int id, byte[] b) + { + InterfaceDefinition iface = new InterfaceDefinition(); + iface.id = id; + if (b[0] == -1) + { + decodeIf3(iface, new InputStream(b)); + } + else + { + decodeIf1(iface, new InputStream(b)); + } + + return iface; + } + + private void decodeIf1(InterfaceDefinition iface, InputStream var1) + { + iface.isIf3 = false; + iface.type = var1.readUnsignedByte(); + iface.menuType = var1.readUnsignedByte(); + iface.contentType = var1.readUnsignedShort(); + iface.originalX = var1.readShort(); + iface.originalY = var1.readShort(); + iface.originalWidth = var1.readUnsignedShort(); + iface.originalHeight = var1.readUnsignedShort(); + iface.opacity = var1.readUnsignedByte(); + iface.parentId = var1.readUnsignedShort(); + if (iface.parentId == 0xFFFF) + { + iface.parentId = -1; + } + else + { + iface.parentId += iface.id & ~0xFFFF; + } + + iface.hoveredSiblingId = var1.readUnsignedShort(); + if (iface.hoveredSiblingId == 0xFFFF) + { + iface.hoveredSiblingId = -1; + } + + int var2 = var1.readUnsignedByte(); + int var3; + if (var2 > 0) + { + iface.alternateOperators = new int[var2]; + iface.alternateRhs = new int[var2]; + + for (var3 = 0; var3 < var2; ++var3) + { + iface.alternateOperators[var3] = var1.readUnsignedByte(); + iface.alternateRhs[var3] = var1.readUnsignedShort(); + } + } + + var3 = var1.readUnsignedByte(); + int var4; + int var5; + int var6; + if (var3 > 0) + { + iface.clientScripts = new ClientScript1Instruction[var3][]; + + for (var4 = 0; var4 < var3; ++var4) + { + var5 = var1.readUnsignedShort(); + int[] bytecode = new int[var5]; + + for (var6 = 0; var6 < var5; ++var6) + { + bytecode[var6] = var1.readUnsignedShort(); + if (bytecode[var6] == 0xFFFF) + { + bytecode[var6] = -1; + } + + List instructions = new ArrayList<>(); + for (int i = 0; i < bytecode.length;) + { + ClientScript1Instruction ins = new ClientScript1Instruction(); + + ins.opcode = ClientScript1Instruction.Opcode.values()[bytecode[i++]]; + + int ac = ins.opcode.argumentCount; + ins.operands = Arrays.copyOfRange(bytecode, i, i + ac); + + instructions.add(ins); + i += ac; + } + iface.clientScripts[var4] = instructions.toArray(new ClientScript1Instruction[0]); + } + } + } + + if (iface.type == 0) + { + iface.scrollHeight = var1.readUnsignedShort(); + iface.isHidden = var1.readUnsignedByte() == 1; + } + + if (iface.type == 1) + { + var1.readUnsignedShort(); + var1.readUnsignedByte(); + } + + if (iface.type == 2) + { + iface.itemIds = new int[iface.originalWidth * iface.originalHeight]; + iface.itemQuantities = new int[iface.originalHeight * iface.originalWidth]; + var4 = var1.readUnsignedByte(); + if (var4 == 1) + { + iface.clickMask |= 268435456; + } + + var5 = var1.readUnsignedByte(); + if (var5 == 1) + { + iface.clickMask |= 1073741824; + } + + var6 = var1.readUnsignedByte(); + if (var6 == 1) + { + iface.clickMask |= Integer.MIN_VALUE; + } + + int var7 = var1.readUnsignedByte(); + if (var7 == 1) + { + iface.clickMask |= 536870912; + } + + iface.xPitch = var1.readUnsignedByte(); + iface.yPitch = var1.readUnsignedByte(); + iface.xOffsets = new int[20]; + iface.yOffsets = new int[20]; + iface.sprites = new int[20]; + + int var8; + for (var8 = 0; var8 < 20; ++var8) + { + int var9 = var1.readUnsignedByte(); + if (var9 == 1) + { + iface.xOffsets[var8] = var1.readShort(); + iface.yOffsets[var8] = var1.readShort(); + iface.sprites[var8] = var1.readInt(); + } + else + { + iface.sprites[var8] = -1; + } + } + + iface.configActions = new String[5]; + + for (var8 = 0; var8 < 5; ++var8) + { + String var11 = var1.readString(); + if (var11.length() > 0) + { + iface.configActions[var8] = var11; + iface.clickMask |= 1 << var8 + 23; + } + } + } + + if (iface.type == 3) + { + iface.filled = var1.readUnsignedByte() == 1; + } + + if (iface.type == 4 || iface.type == 1) + { + iface.xTextAlignment = var1.readUnsignedByte(); + iface.yTextAlignment = var1.readUnsignedByte(); + iface.lineHeight = var1.readUnsignedByte(); + iface.fontId = var1.readUnsignedShort(); + if (iface.fontId == 0xFFFF) + { + iface.fontId = -1; + } + + iface.textShadowed = var1.readUnsignedByte() == 1; + } + + if (iface.type == 4) + { + iface.text = var1.readString(); + iface.alternateText = var1.readString(); + } + + if (iface.type == 1 || iface.type == 3 || iface.type == 4) + { + iface.textColor = var1.readInt(); + } + + if (iface.type == 3 || iface.type == 4) + { + iface.alternateTextColor = var1.readInt(); + iface.hoveredTextColor = var1.readInt(); + iface.alternateHoveredTextColor = var1.readInt(); + } + + if (iface.type == 5) + { + iface.spriteId = var1.readInt(); + iface.alternateSpriteId = var1.readInt(); + } + + if (iface.type == 6) + { + iface.modelType = 1; + iface.modelId = var1.readUnsignedShort(); + if (iface.modelId == 0xFFFF) + { + iface.modelId = -1; + } + + iface.alternateModelId = var1.readUnsignedShort(); + if (iface.alternateModelId == 0xFFFF) + { + iface.alternateModelId = -1; + } + + iface.animation = var1.readUnsignedShort(); + if (iface.animation == 0xFFFF) + { + iface.animation = -1; + } + + iface.alternateAnimation = var1.readUnsignedShort(); + if (iface.alternateAnimation == 0xFFFF) + { + iface.alternateAnimation = -1; + } + + iface.modelZoom = var1.readUnsignedShort(); + iface.rotationX = var1.readUnsignedShort(); + iface.rotationZ = var1.readUnsignedShort(); + } + + if (iface.type == 7) + { + iface.itemIds = new int[iface.originalWidth * iface.originalHeight]; + iface.itemQuantities = new int[iface.originalWidth * iface.originalHeight]; + iface.xTextAlignment = var1.readUnsignedByte(); + iface.fontId = var1.readUnsignedShort(); + if (iface.fontId == 0xFFFF) + { + iface.fontId = -1; + } + + iface.textShadowed = var1.readUnsignedByte() == 1; + iface.textColor = var1.readInt(); + iface.xPitch = var1.readShort(); + iface.yPitch = var1.readShort(); + var4 = var1.readUnsignedByte(); + if (var4 == 1) + { + iface.clickMask |= 1073741824; + } + + iface.configActions = new String[5]; + + for (var5 = 0; var5 < 5; ++var5) + { + String var10 = var1.readString(); + if (var10.length() > 0) + { + iface.configActions[var5] = var10; + iface.clickMask |= 1 << var5 + 23; + } + } + } + + if (iface.type == 8) + { + iface.text = var1.readString(); + } + + if (iface.menuType == 2 || iface.type == 2) + { + iface.targetVerb = var1.readString(); + iface.spellName = var1.readString(); + var4 = var1.readUnsignedShort() & 63; + iface.clickMask |= var4 << 11; + } + + if (iface.menuType == 1 || iface.menuType == 4 || iface.menuType == 5 || iface.menuType == 6) + { + iface.tooltip = var1.readString(); + if (iface.tooltip.length() == 0) + { + if (iface.menuType == 1) + { + iface.tooltip = "Ok"; + } + + if (iface.menuType == 4) + { + iface.tooltip = "Select"; + } + + if (iface.menuType == 5) + { + iface.tooltip = "Select"; + } + + if (iface.menuType == 6) + { + iface.tooltip = "Continue"; + } + } + } + + if (iface.menuType == 1 || iface.menuType == 4 || iface.menuType == 5) + { + iface.clickMask |= 4194304; + } + + if (iface.menuType == 6) + { + iface.clickMask |= 1; + } + + } + + private void decodeIf3(InterfaceDefinition iface, InputStream var1) + { + var1.readUnsignedByte(); + iface.isIf3 = true; + iface.type = var1.readUnsignedByte(); + iface.contentType = var1.readUnsignedShort(); + iface.originalX = var1.readShort(); + iface.originalY = var1.readShort(); + iface.originalWidth = var1.readUnsignedShort(); + if (iface.type == 9) + { + iface.originalHeight = var1.readShort(); + } + else + { + iface.originalHeight = var1.readUnsignedShort(); + } + + iface.widthMode = var1.readByte(); + iface.heightMode = var1.readByte(); + iface.xPositionMode = var1.readByte(); + iface.yPositionMode = var1.readByte(); + iface.parentId = var1.readUnsignedShort(); + if (iface.parentId == 0xFFFF) + { + iface.parentId = -1; + } + else + { + iface.parentId += iface.id & ~0xFFFF; + } + + iface.isHidden = var1.readUnsignedByte() == 1; + if (iface.type == 0) + { + iface.scrollWidth = var1.readUnsignedShort(); + iface.scrollHeight = var1.readUnsignedShort(); + iface.noClickThrough = var1.readUnsignedByte() == 1; + } + + if (iface.type == 5) + { + iface.spriteId = var1.readInt(); + iface.textureId = var1.readUnsignedShort(); + iface.spriteTiling = var1.readUnsignedByte() == 1; + iface.opacity = var1.readUnsignedByte(); + iface.borderType = var1.readUnsignedByte(); + iface.shadowColor = var1.readInt(); + iface.flippedVertically = var1.readUnsignedByte() == 1; + iface.flippedHorizontally = var1.readUnsignedByte() == 1; + } + + if (iface.type == 6) + { + iface.modelType = 1; + iface.modelId = var1.readUnsignedShort(); + if (iface.modelId == 0xFFFF) + { + iface.modelId = -1; + } + + iface.offsetX2d = var1.readShort(); + iface.offsetY2d = var1.readShort(); + iface.rotationX = var1.readUnsignedShort(); + iface.rotationZ = var1.readUnsignedShort(); + iface.rotationY = var1.readUnsignedShort(); + iface.modelZoom = var1.readUnsignedShort(); + iface.animation = var1.readUnsignedShort(); + if (iface.animation == 0xFFFF) + { + iface.animation = -1; + } + + iface.orthogonal = var1.readUnsignedByte() == 1; + var1.readUnsignedShort(); + if (iface.widthMode != 0) + { + iface.modelHeightOverride = var1.readUnsignedShort(); + } + + if (iface.heightMode != 0) + { + var1.readUnsignedShort(); + } + } + + if (iface.type == 4) + { + iface.fontId = var1.readUnsignedShort(); + if (iface.fontId == 0xFFFF) + { + iface.fontId = -1; + } + + iface.text = var1.readString(); + iface.lineHeight = var1.readUnsignedByte(); + iface.xTextAlignment = var1.readUnsignedByte(); + iface.yTextAlignment = var1.readUnsignedByte(); + iface.textShadowed = var1.readUnsignedByte() == 1; + iface.textColor = var1.readInt(); + } + + if (iface.type == 3) + { + iface.textColor = var1.readInt(); + iface.filled = var1.readUnsignedByte() == 1; + iface.opacity = var1.readUnsignedByte(); + } + + if (iface.type == 9) + { + iface.lineWidth = var1.readUnsignedByte(); + iface.textColor = var1.readInt(); + iface.lineDirection = var1.readUnsignedByte() == 1; + } + + iface.clickMask = var1.read24BitInt(); + iface.name = var1.readString(); + int var2 = var1.readUnsignedByte(); + if (var2 > 0) + { + iface.actions = new String[var2]; + + for (int var3 = 0; var3 < var2; ++var3) + { + iface.actions[var3] = var1.readString(); + } + } + + iface.dragDeadZone = var1.readUnsignedByte(); + iface.dragDeadTime = var1.readUnsignedByte(); + iface.dragRenderBehavior = var1.readUnsignedByte() == 1; + iface.targetVerb = var1.readString(); + iface.onLoadListener = this.decodeListener(iface, var1); + iface.onMouseOverListener = this.decodeListener(iface, var1); + iface.onMouseLeaveListener = this.decodeListener(iface, var1); + iface.onTargetLeaveListener = this.decodeListener(iface, var1); + iface.onTargetEnterListener = this.decodeListener(iface, var1); + iface.onVarTransmitListener = this.decodeListener(iface, var1); + iface.onInvTransmitListener = this.decodeListener(iface, var1); + iface.onStatTransmitListener = this.decodeListener(iface, var1); + iface.onTimerListener = this.decodeListener(iface, var1); + iface.onOpListener = this.decodeListener(iface, var1); + iface.onMouseRepeatListener = this.decodeListener(iface, var1); + iface.onClickListener = this.decodeListener(iface, var1); + iface.onClickRepeatListener = this.decodeListener(iface, var1); + iface.onReleaseListener = this.decodeListener(iface, var1); + iface.onHoldListener = this.decodeListener(iface, var1); + iface.onDragListener = this.decodeListener(iface, var1); + iface.onDragCompleteListener = this.decodeListener(iface, var1); + iface.onScrollWheelListener = this.decodeListener(iface, var1); + iface.varTransmitTriggers = this.decodeTriggers(var1); + iface.invTransmitTriggers = this.decodeTriggers(var1); + iface.statTransmitTriggers = this.decodeTriggers(var1); + } + + private Object[] decodeListener(InterfaceDefinition iface, InputStream var1) + { + int var2 = var1.readUnsignedByte(); + if (var2 == 0) + { + return null; + } + else + { + Object[] var3 = new Object[var2]; + + for (int var4 = 0; var4 < var2; ++var4) + { + int var5 = var1.readUnsignedByte(); + if (var5 == 0) + { + var3[var4] = new Integer(var1.readInt()); + } + else if (var5 == 1) + { + var3[var4] = var1.readString(); + } + } + + iface.hasListener = true; + return var3; + } + } + + private int[] decodeTriggers(InputStream var1) + { + int var2 = var1.readUnsignedByte(); + if (var2 == 0) + { + return null; + } + else + { + int[] var3 = new int[var2]; + + for (int var4 = 0; var4 < var2; ++var4) + { + var3[var4] = var1.readInt(); + } + + return var3; + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/InventoryLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/InventoryLoader.java new file mode 100644 index 0000000..b93cac4 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/InventoryLoader.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.InventoryDefinition; +import net.runelite.cache.io.InputStream; + +public class InventoryLoader +{ + public InventoryDefinition load(int id, byte[] b) + { + InventoryDefinition def = new InventoryDefinition(); + def.id = id; + InputStream is = new InputStream(b); + + while (true) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + if (opcode == 2) + { + def.size = is.readUnsignedShort(); + } + } + + return def; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/ItemLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/ItemLoader.java new file mode 100644 index 0000000..806fa3e --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/ItemLoader.java @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.definitions.loaders; + +import java.util.HashMap; +import net.runelite.cache.definitions.ItemDefinition; +import net.runelite.cache.io.InputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ItemLoader +{ + private static final Logger logger = LoggerFactory.getLogger(ItemLoader.class); + + public ItemDefinition load(int id, byte[] b) + { + ItemDefinition def = new ItemDefinition(id); + InputStream is = new InputStream(b); + + while (true) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + this.decodeValues(opcode, def, is); + } + + return def; + } + + private void decodeValues(int opcode, ItemDefinition def, InputStream stream) + { + if (opcode == 1) + { + def.inventoryModel = stream.readUnsignedShort(); + } + else if (opcode == 2) + { + def.name = stream.readString(); + } + else if (opcode == 4) + { + def.zoom2d = stream.readUnsignedShort(); + } + else if (opcode == 5) + { + def.xan2d = stream.readUnsignedShort(); + } + else if (opcode == 6) + { + def.yan2d = stream.readUnsignedShort(); + } + else if (opcode == 7) + { + def.xOffset2d = stream.readUnsignedShort(); + if (def.xOffset2d > 32767) + { + def.xOffset2d -= 65536; + } + } + else if (opcode == 8) + { + def.yOffset2d = stream.readUnsignedShort(); + if (def.yOffset2d > 32767) + { + def.yOffset2d -= 65536; + } + } + else if (opcode == 11) + { + def.stackable = 1; + } + else if (opcode == 12) + { + def.cost = stream.readInt(); + } + else if (opcode == 16) + { + def.members = true; + } + else if (opcode == 23) + { + def.maleModel0 = stream.readUnsignedShort(); + def.maleOffset = stream.readUnsignedByte(); + } + else if (opcode == 24) + { + def.maleModel1 = stream.readUnsignedShort(); + } + else if (opcode == 25) + { + def.femaleModel0 = stream.readUnsignedShort(); + def.femaleOffset = stream.readUnsignedByte(); + } + else if (opcode == 26) + { + def.femaleModel1 = stream.readUnsignedShort(); + } + else if (opcode >= 30 && opcode < 35) + { + def.options[opcode - 30] = stream.readString(); + if (def.options[opcode - 30].equalsIgnoreCase("Hidden")) + { + def.options[opcode - 30] = null; + } + } + else if (opcode >= 35 && opcode < 40) + { + def.interfaceOptions[opcode - 35] = stream.readString(); + } + else if (opcode == 40) + { + int var5 = stream.readUnsignedByte(); + def.colorFind = new short[var5]; + def.colorReplace = new short[var5]; + + for (int var4 = 0; var4 < var5; ++var4) + { + def.colorFind[var4] = (short) stream.readUnsignedShort(); + def.colorReplace[var4] = (short) stream.readUnsignedShort(); + } + + } + else if (opcode == 41) + { + int var5 = stream.readUnsignedByte(); + def.textureFind = new short[var5]; + def.textureReplace = new short[var5]; + + for (int var4 = 0; var4 < var5; ++var4) + { + def.textureFind[var4] = (short) stream.readUnsignedShort(); + def.textureReplace[var4] = (short) stream.readUnsignedShort(); + } + + } + else if (opcode == 42) + { + def.shiftClickDropIndex = stream.readByte(); + } + else if (opcode == 65) + { + def.isTradeable = true; + } + else if (opcode == 78) + { + def.maleModel2 = stream.readUnsignedShort(); + } + else if (opcode == 79) + { + def.femaleModel2 = stream.readUnsignedShort(); + } + else if (opcode == 90) + { + def.maleHeadModel = stream.readUnsignedShort(); + } + else if (opcode == 91) + { + def.femaleHeadModel = stream.readUnsignedShort(); + } + else if (opcode == 92) + { + def.maleHeadModel2 = stream.readUnsignedShort(); + } + else if (opcode == 93) + { + def.femaleHeadModel2 = stream.readUnsignedShort(); + } + else if (opcode == 95) + { + def.zan2d = stream.readUnsignedShort(); + } + else if (opcode == 97) + { + def.notedID = stream.readUnsignedShort(); + } + else if (opcode == 98) + { + def.notedTemplate = stream.readUnsignedShort(); + } + else if (opcode >= 100 && opcode < 110) + { + if (def.countObj == null) + { + def.countObj = new int[10]; + def.countCo = new int[10]; + } + + def.countObj[opcode - 100] = stream.readUnsignedShort(); + def.countCo[opcode - 100] = stream.readUnsignedShort(); + } + else if (opcode == 110) + { + def.resizeX = stream.readUnsignedShort(); + } + else if (opcode == 111) + { + def.resizeY = stream.readUnsignedShort(); + } + else if (opcode == 112) + { + def.resizeZ = stream.readUnsignedShort(); + } + else if (opcode == 113) + { + def.ambient = stream.readByte(); + } + else if (opcode == 114) + { + def.contrast = stream.readByte(); + } + else if (opcode == 115) + { + def.team = stream.readUnsignedByte(); + } + else if (opcode == 139) + { + def.boughtId = stream.readUnsignedShort(); + } + else if (opcode == 140) + { + def.boughtTemplateId = stream.readUnsignedShort(); + } + else if (opcode == 148) + { + def.placeholderId = stream.readUnsignedShort(); + } + else if (opcode == 149) + { + def.placeholderTemplateId = stream.readUnsignedShort(); + } + else if (opcode == 249) + { + int length = stream.readUnsignedByte(); + + def.params = new HashMap<>(length); + + for (int i = 0; i < length; i++) + { + boolean isString = stream.readUnsignedByte() == 1; + int key = stream.read24BitInt(); + Object value; + + if (isString) + { + value = stream.readString(); + } + + else + { + value = stream.readInt(); + } + + def.params.put(key, value); + } + } + else + { + logger.warn("Unrecognized opcode {}", opcode); + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/KitLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/KitLoader.java new file mode 100644 index 0000000..9bd3f89 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/KitLoader.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.KitDefinition; +import net.runelite.cache.io.InputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class KitLoader +{ + private static final Logger logger = LoggerFactory.getLogger(KitLoader.class); + + public KitDefinition load(int id, byte[] b) + { + KitDefinition def = new KitDefinition(id); + InputStream is = new InputStream(b); + + for (;;) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + if (opcode == 1) + { + def.bodyPartId = is.readUnsignedByte(); + } + else if (opcode == 2) + { + int length = is.readUnsignedByte(); + def.modelIds = new int[length]; + + for (int index = 0; index < length; ++index) + { + def.modelIds[index] = is.readUnsignedShort(); + } + } + else if (opcode == 3) + { + def.nonSelectable = true; + } + else if (opcode == 40) + { + int length = is.readUnsignedByte(); + def.recolorToFind = new short[length]; + def.recolorToReplace = new short[length]; + + for (int index = 0; index < length; ++index) + { + def.recolorToFind[index] = is.readShort(); + def.recolorToReplace[index] = is.readShort(); + } + } + else if (opcode == 41) + { + int length = is.readUnsignedByte(); + def.retextureToFind = new short[length]; + def.retextureToReplace = new short[length]; + + for (int index = 0; index < length; ++index) + { + def.retextureToFind[index] = is.readShort(); + def.retextureToReplace[index] = is.readShort(); + } + } + else if (opcode >= 60 && opcode < 70) + { + def.models[opcode - 60] = is.readShort(); + } + } + + return def; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/LocationsLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/LocationsLoader.java new file mode 100644 index 0000000..4dab72c --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/LocationsLoader.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.LocationsDefinition; +import net.runelite.cache.io.InputStream; +import net.runelite.cache.region.Location; +import net.runelite.cache.region.Position; + +public class LocationsLoader +{ + public LocationsDefinition load(int regionX, int regionY, byte[] b) + { + LocationsDefinition loc = new LocationsDefinition(); + loc.setRegionX(regionX); + loc.setRegionY(regionY); + loadLocations(loc, b); + return loc; + } + + private void loadLocations(LocationsDefinition loc, byte[] b) + { + InputStream buf = new InputStream(b); + + int id = -1; + int idOffset; + + while ((idOffset = buf.readUnsignedIntSmartShortCompat()) != 0) + { + id += idOffset; + + int position = 0; + int positionOffset; + + while ((positionOffset = buf.readUnsignedShortSmart()) != 0) + { + position += positionOffset - 1; + + int localY = position & 0x3F; + int localX = position >> 6 & 0x3F; + int height = position >> 12 & 0x3; + + int attributes = buf.readUnsignedByte(); + int type = attributes >> 2; + int orientation = attributes & 0x3; + + loc.getLocations().add(new Location(id, type, orientation, new Position(localX, localY, height))); + } + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/MapLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/MapLoader.java new file mode 100644 index 0000000..3224536 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/MapLoader.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.MapDefinition; +import net.runelite.cache.definitions.MapDefinition.Tile; +import net.runelite.cache.io.InputStream; +import static net.runelite.cache.region.Region.X; +import static net.runelite.cache.region.Region.Y; +import static net.runelite.cache.region.Region.Z; + +public class MapLoader +{ + public MapDefinition load(int regionX, int regionY, byte[] b) + { + MapDefinition map = new MapDefinition(); + map.setRegionX(regionX); + map.setRegionY(regionY); + loadTerrain(map, b); + return map; + } + + private void loadTerrain(MapDefinition map, byte[] buf) + { + Tile[][][] tiles = map.getTiles(); + + InputStream in = new InputStream(buf); + + for (int z = 0; z < Z; z++) + { + for (int x = 0; x < X; x++) + { + for (int y = 0; y < Y; y++) + { + Tile tile = tiles[z][x][y] = new Tile(); + while (true) + { + int attribute = in.readUnsignedByte(); + if (attribute == 0) + { + break; + } + else if (attribute == 1) + { + int height = in.readUnsignedByte(); + tile.height = height; + break; + } + else if (attribute <= 49) + { + tile.attrOpcode = attribute; + tile.overlayId = in.readByte(); + tile.overlayPath = (byte) ((attribute - 2) / 4); + tile.overlayRotation = (byte) (attribute - 2 & 3); + } + else if (attribute <= 81) + { + tile.settings = (byte) (attribute - 49); + } + else + { + tile.underlayId = (byte) (attribute - 81); + } + } + } + } + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/ModelLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/ModelLoader.java new file mode 100644 index 0000000..4529f8a --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/ModelLoader.java @@ -0,0 +1,750 @@ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.ModelDefinition; +import net.runelite.cache.io.InputStream; + +public class ModelLoader +{ + public ModelDefinition load(int modelId, byte[] b) + { + ModelDefinition def = new ModelDefinition(); + def.id = modelId; + + if (b[b.length - 1] == -1 && b[b.length - 2] == -1) + { + this.load1(def, b); + } + else + { + this.load2(def, b); + } + + def.computeNormals(); + def.computeTextureUVCoordinates(); + def.computeAnimationTables(); + + return def; + } + + private void load1(ModelDefinition model, byte[] var1) + { + InputStream var2 = new InputStream(var1); + InputStream var24 = new InputStream(var1); + InputStream var3 = new InputStream(var1); + InputStream var28 = new InputStream(var1); + InputStream var6 = new InputStream(var1); + InputStream var55 = new InputStream(var1); + InputStream var51 = new InputStream(var1); + var2.setOffset(var1.length - 23); + int verticeCount = var2.readUnsignedShort(); + int triangleCount = var2.readUnsignedShort(); + int textureTriangleCount = var2.readUnsignedByte(); + int var13 = var2.readUnsignedByte(); + int modelPriority = var2.readUnsignedByte(); + int var50 = var2.readUnsignedByte(); + int var17 = var2.readUnsignedByte(); + int modelTexture = var2.readUnsignedByte(); + int modelVertexSkins = var2.readUnsignedByte(); + int var20 = var2.readUnsignedShort(); + int var21 = var2.readUnsignedShort(); + int var42 = var2.readUnsignedShort(); + int var22 = var2.readUnsignedShort(); + int var38 = var2.readUnsignedShort(); + int textureAmount = 0; + int var7 = 0; + int var29 = 0; + int position; + if (textureTriangleCount > 0) + { + model.textureRenderTypes = new byte[textureTriangleCount]; + var2.setOffset(0); + + for (position = 0; position < textureTriangleCount; ++position) + { + byte renderType = model.textureRenderTypes[position] = var2.readByte(); + if (renderType == 0) + { + ++textureAmount; + } + + if (renderType >= 1 && renderType <= 3) + { + ++var7; + } + + if (renderType == 2) + { + ++var29; + } + } + } + + position = textureTriangleCount + verticeCount; + int renderTypePos = position; + if (var13 == 1) + { + position += triangleCount; + } + + int var49 = position; + position += triangleCount; + int priorityPos = position; + if (modelPriority == 255) + { + position += triangleCount; + } + + int triangleSkinPos = position; + if (var17 == 1) + { + position += triangleCount; + } + + int var35 = position; + if (modelVertexSkins == 1) + { + position += verticeCount; + } + + int alphaPos = position; + if (var50 == 1) + { + position += triangleCount; + } + + int var11 = position; + position += var22; + int texturePos = position; + if (modelTexture == 1) + { + position += triangleCount * 2; + } + + int textureCoordPos = position; + position += var38; + int colorPos = position; + position += triangleCount * 2; + int var40 = position; + position += var20; + int var41 = position; + position += var21; + int var8 = position; + position += var42; + int var43 = position; + position += textureAmount * 6; + int var37 = position; + position += var7 * 6; + int var48 = position; + position += var7 * 6; + int var56 = position; + position += var7 * 2; + int var45 = position; + position += var7; + int var46 = position; + position += var7 * 2 + var29 * 2; + model.vertexCount = verticeCount; + model.faceCount = triangleCount; + model.textureTriangleCount = textureTriangleCount; + model.vertexPositionsX = new int[verticeCount]; + model.vertexPositionsY = new int[verticeCount]; + model.vertexPositionsZ = new int[verticeCount]; + model.faceVertexIndices1 = new int[triangleCount]; + model.faceVertexIndices2 = new int[triangleCount]; + model.faceVertexIndices3 = new int[triangleCount]; + if (modelVertexSkins == 1) + { + model.vertexSkins = new int[verticeCount]; + } + + if (var13 == 1) + { + model.faceRenderTypes = new byte[triangleCount]; + } + + if (modelPriority == 255) + { + model.faceRenderPriorities = new byte[triangleCount]; + } + else + { + model.priority = (byte) modelPriority; + } + + if (var50 == 1) + { + model.faceAlphas = new byte[triangleCount]; + } + + if (var17 == 1) + { + model.faceSkins = new int[triangleCount]; + } + + if (modelTexture == 1) + { + model.faceTextures = new short[triangleCount]; + } + + if (modelTexture == 1 && textureTriangleCount > 0) + { + model.textureCoordinates = new byte[triangleCount]; + } + + model.faceColors = new short[triangleCount]; + if (textureTriangleCount > 0) + { + model.textureTriangleVertexIndices1 = new short[textureTriangleCount]; + model.textureTriangleVertexIndices2 = new short[textureTriangleCount]; + model.textureTriangleVertexIndices3 = new short[textureTriangleCount]; + if (var7 > 0) + { + model.aShortArray2574 = new short[var7]; + model.aShortArray2575 = new short[var7]; + model.aShortArray2586 = new short[var7]; + model.aShortArray2577 = new short[var7]; + model.aByteArray2580 = new byte[var7]; + model.aShortArray2578 = new short[var7]; + } + + if (var29 > 0) + { + model.texturePrimaryColors = new short[var29]; + } + } + + var2.setOffset(textureTriangleCount); + var24.setOffset(var40); + var3.setOffset(var41); + var28.setOffset(var8); + var6.setOffset(var35); + int vX = 0; + int vY = 0; + int vZ = 0; + + int vertexZOffset; + int var10; + int vertexYOffset; + int var15; + int point; + for (point = 0; point < verticeCount; ++point) + { + int vertexFlags = var2.readUnsignedByte(); + int vertexXOffset = 0; + if ((vertexFlags & 1) != 0) + { + vertexXOffset = var24.readShortSmart(); + } + + vertexYOffset = 0; + if ((vertexFlags & 2) != 0) + { + vertexYOffset = var3.readShortSmart(); + } + + vertexZOffset = 0; + if ((vertexFlags & 4) != 0) + { + vertexZOffset = var28.readShortSmart(); + } + + model.vertexPositionsX[point] = vX + vertexXOffset; + model.vertexPositionsY[point] = vY + vertexYOffset; + model.vertexPositionsZ[point] = vZ + vertexZOffset; + vX = model.vertexPositionsX[point]; + vY = model.vertexPositionsY[point]; + vZ = model.vertexPositionsZ[point]; + if (modelVertexSkins == 1) + { + model.vertexSkins[point] = var6.readUnsignedByte(); + } + } + + var2.setOffset(colorPos); + var24.setOffset(renderTypePos); + var3.setOffset(priorityPos); + var28.setOffset(alphaPos); + var6.setOffset(triangleSkinPos); + var55.setOffset(texturePos); + var51.setOffset(textureCoordPos); + + for (point = 0; point < triangleCount; ++point) + { + model.faceColors[point] = (short) var2.readUnsignedShort(); + if (var13 == 1) + { + model.faceRenderTypes[point] = var24.readByte(); + } + + if (modelPriority == 255) + { + model.faceRenderPriorities[point] = var3.readByte(); + } + + if (var50 == 1) + { + model.faceAlphas[point] = var28.readByte(); + } + + if (var17 == 1) + { + model.faceSkins[point] = var6.readUnsignedByte(); + } + + if (modelTexture == 1) + { + model.faceTextures[point] = (short) (var55.readUnsignedShort() - 1); + } + + if (model.textureCoordinates != null && model.faceTextures[point] != -1) + { + model.textureCoordinates[point] = (byte) (var51.readUnsignedByte() - 1); + } + } + + var2.setOffset(var11); + var24.setOffset(var49); + int trianglePointX = 0; + int trianglePointY = 0; + int trianglePointZ = 0; + vertexYOffset = 0; + + int var16; + for (vertexZOffset = 0; vertexZOffset < triangleCount; ++vertexZOffset) + { + int numFaces = var24.readUnsignedByte(); + if (numFaces == 1) + { + trianglePointX = var2.readShortSmart() + vertexYOffset; + trianglePointY = var2.readShortSmart() + trianglePointX; + trianglePointZ = var2.readShortSmart() + trianglePointY; + vertexYOffset = trianglePointZ; + model.faceVertexIndices1[vertexZOffset] = trianglePointX; + model.faceVertexIndices2[vertexZOffset] = trianglePointY; + model.faceVertexIndices3[vertexZOffset] = trianglePointZ; + } + + if (numFaces == 2) + { + trianglePointY = trianglePointZ; + trianglePointZ = var2.readShortSmart() + vertexYOffset; + vertexYOffset = trianglePointZ; + model.faceVertexIndices1[vertexZOffset] = trianglePointX; + model.faceVertexIndices2[vertexZOffset] = trianglePointY; + model.faceVertexIndices3[vertexZOffset] = trianglePointZ; + } + + if (numFaces == 3) + { + trianglePointX = trianglePointZ; + trianglePointZ = var2.readShortSmart() + vertexYOffset; + vertexYOffset = trianglePointZ; + model.faceVertexIndices1[vertexZOffset] = trianglePointX; + model.faceVertexIndices2[vertexZOffset] = trianglePointY; + model.faceVertexIndices3[vertexZOffset] = trianglePointZ; + } + + if (numFaces == 4) + { + int var57 = trianglePointX; + trianglePointX = trianglePointY; + trianglePointY = var57; + trianglePointZ = var2.readShortSmart() + vertexYOffset; + vertexYOffset = trianglePointZ; + model.faceVertexIndices1[vertexZOffset] = trianglePointX; + model.faceVertexIndices2[vertexZOffset] = var57; + model.faceVertexIndices3[vertexZOffset] = trianglePointZ; + } + } + + var2.setOffset(var43); + var24.setOffset(var37); + var3.setOffset(var48); + var28.setOffset(var56); + var6.setOffset(var45); + var55.setOffset(var46); + + for (int texIndex = 0; texIndex < textureTriangleCount; ++texIndex) + { + int type = model.textureRenderTypes[texIndex] & 255; + if (type == 0) + { + model.textureTriangleVertexIndices1[texIndex] = (short) var2.readUnsignedShort(); + model.textureTriangleVertexIndices2[texIndex] = (short) var2.readUnsignedShort(); + model.textureTriangleVertexIndices3[texIndex] = (short) var2.readUnsignedShort(); + } + + if (type == 1) + { + model.textureTriangleVertexIndices1[texIndex] = (short) var24.readUnsignedShort(); + model.textureTriangleVertexIndices2[texIndex] = (short) var24.readUnsignedShort(); + model.textureTriangleVertexIndices3[texIndex] = (short) var24.readUnsignedShort(); + model.aShortArray2574[texIndex] = (short) var3.readUnsignedShort(); + model.aShortArray2575[texIndex] = (short) var3.readUnsignedShort(); + model.aShortArray2586[texIndex] = (short) var3.readUnsignedShort(); + model.aShortArray2577[texIndex] = (short) var28.readUnsignedShort(); + model.aByteArray2580[texIndex] = var6.readByte(); + model.aShortArray2578[texIndex] = (short) var55.readUnsignedShort(); + } + + if (type == 2) + { + model.textureTriangleVertexIndices1[texIndex] = (short) var24.readUnsignedShort(); + model.textureTriangleVertexIndices2[texIndex] = (short) var24.readUnsignedShort(); + model.textureTriangleVertexIndices3[texIndex] = (short) var24.readUnsignedShort(); + model.aShortArray2574[texIndex] = (short) var3.readUnsignedShort(); + model.aShortArray2575[texIndex] = (short) var3.readUnsignedShort(); + model.aShortArray2586[texIndex] = (short) var3.readUnsignedShort(); + model.aShortArray2577[texIndex] = (short) var28.readUnsignedShort(); + model.aByteArray2580[texIndex] = var6.readByte(); + model.aShortArray2578[texIndex] = (short) var55.readUnsignedShort(); + model.texturePrimaryColors[texIndex] = (short) var55.readUnsignedShort(); + } + + if (type == 3) + { + model.textureTriangleVertexIndices1[texIndex] = (short) var24.readUnsignedShort(); + model.textureTriangleVertexIndices2[texIndex] = (short) var24.readUnsignedShort(); + model.textureTriangleVertexIndices3[texIndex] = (short) var24.readUnsignedShort(); + model.aShortArray2574[texIndex] = (short) var3.readUnsignedShort(); + model.aShortArray2575[texIndex] = (short) var3.readUnsignedShort(); + model.aShortArray2586[texIndex] = (short) var3.readUnsignedShort(); + model.aShortArray2577[texIndex] = (short) var28.readUnsignedShort(); + model.aByteArray2580[texIndex] = var6.readByte(); + model.aShortArray2578[texIndex] = (short) var55.readUnsignedShort(); + } + } + + var2.setOffset(position); + vertexZOffset = var2.readUnsignedByte(); + if (vertexZOffset != 0) + { + //new Class41(); + var2.readUnsignedShort(); + var2.readUnsignedShort(); + var2.readUnsignedShort(); + var2.readInt(); + } + } + + private void load2(ModelDefinition model, byte[] var1) + { + boolean var2 = false; + boolean var43 = false; + InputStream var5 = new InputStream(var1); + InputStream var39 = new InputStream(var1); + InputStream var26 = new InputStream(var1); + InputStream var9 = new InputStream(var1); + InputStream var3 = new InputStream(var1); + var5.setOffset(var1.length - 18); + int var10 = var5.readUnsignedShort(); + int var11 = var5.readUnsignedShort(); + int var12 = var5.readUnsignedByte(); + int var13 = var5.readUnsignedByte(); + int var14 = var5.readUnsignedByte(); + int var30 = var5.readUnsignedByte(); + int var15 = var5.readUnsignedByte(); + int var28 = var5.readUnsignedByte(); + int var27 = var5.readUnsignedShort(); + int var20 = var5.readUnsignedShort(); + int var36 = var5.readUnsignedShort(); + int var23 = var5.readUnsignedShort(); + byte var16 = 0; + int var46 = var16 + var10; + int var24 = var46; + var46 += var11; + int var25 = var46; + if (var14 == 255) + { + var46 += var11; + } + + int var4 = var46; + if (var15 == 1) + { + var46 += var11; + } + + int var42 = var46; + if (var13 == 1) + { + var46 += var11; + } + + int var37 = var46; + if (var28 == 1) + { + var46 += var10; + } + + int var29 = var46; + if (var30 == 1) + { + var46 += var11; + } + + int var44 = var46; + var46 += var23; + int var17 = var46; + var46 += var11 * 2; + int var32 = var46; + var46 += var12 * 6; + int var34 = var46; + var46 += var27; + int var35 = var46; + var46 += var20; + int var10000 = var46 + var36; + model.vertexCount = var10; + model.faceCount = var11; + model.textureTriangleCount = var12; + model.vertexPositionsX = new int[var10]; + model.vertexPositionsY = new int[var10]; + model.vertexPositionsZ = new int[var10]; + model.faceVertexIndices1 = new int[var11]; + model.faceVertexIndices2 = new int[var11]; + model.faceVertexIndices3 = new int[var11]; + if (var12 > 0) + { + model.textureRenderTypes = new byte[var12]; + model.textureTriangleVertexIndices1 = new short[var12]; + model.textureTriangleVertexIndices2 = new short[var12]; + model.textureTriangleVertexIndices3 = new short[var12]; + } + + if (var28 == 1) + { + model.vertexSkins = new int[var10]; + } + + if (var13 == 1) + { + model.faceRenderTypes = new byte[var11]; + model.textureCoordinates = new byte[var11]; + model.faceTextures = new short[var11]; + } + + if (var14 == 255) + { + model.faceRenderPriorities = new byte[var11]; + } + else + { + model.priority = (byte) var14; + } + + if (var30 == 1) + { + model.faceAlphas = new byte[var11]; + } + + if (var15 == 1) + { + model.faceSkins = new int[var11]; + } + + model.faceColors = new short[var11]; + var5.setOffset(var16); + var39.setOffset(var34); + var26.setOffset(var35); + var9.setOffset(var46); + var3.setOffset(var37); + int var41 = 0; + int var33 = 0; + int var19 = 0; + + int var6; + int var7; + int var8; + int var18; + int var31; + for (var18 = 0; var18 < var10; ++var18) + { + var8 = var5.readUnsignedByte(); + var31 = 0; + if ((var8 & 1) != 0) + { + var31 = var39.readShortSmart(); + } + + var6 = 0; + if ((var8 & 2) != 0) + { + var6 = var26.readShortSmart(); + } + + var7 = 0; + if ((var8 & 4) != 0) + { + var7 = var9.readShortSmart(); + } + + model.vertexPositionsX[var18] = var41 + var31; + model.vertexPositionsY[var18] = var33 + var6; + model.vertexPositionsZ[var18] = var19 + var7; + var41 = model.vertexPositionsX[var18]; + var33 = model.vertexPositionsY[var18]; + var19 = model.vertexPositionsZ[var18]; + if (var28 == 1) + { + model.vertexSkins[var18] = var3.readUnsignedByte(); + } + } + + var5.setOffset(var17); + var39.setOffset(var42); + var26.setOffset(var25); + var9.setOffset(var29); + var3.setOffset(var4); + + for (var18 = 0; var18 < var11; ++var18) + { + model.faceColors[var18] = (short) var5.readUnsignedShort(); + if (var13 == 1) + { + var8 = var39.readUnsignedByte(); + if ((var8 & 1) == 1) + { + model.faceRenderTypes[var18] = 1; + var2 = true; + } + else + { + model.faceRenderTypes[var18] = 0; + } + + if ((var8 & 2) == 2) + { + model.textureCoordinates[var18] = (byte) (var8 >> 2); + model.faceTextures[var18] = model.faceColors[var18]; + model.faceColors[var18] = 127; + if (model.faceTextures[var18] != -1) + { + var43 = true; + } + } + else + { + model.textureCoordinates[var18] = -1; + model.faceTextures[var18] = -1; + } + } + + if (var14 == 255) + { + model.faceRenderPriorities[var18] = var26.readByte(); + } + + if (var30 == 1) + { + model.faceAlphas[var18] = var9.readByte(); + } + + if (var15 == 1) + { + model.faceSkins[var18] = var3.readUnsignedByte(); + } + } + + var5.setOffset(var44); + var39.setOffset(var24); + var18 = 0; + var8 = 0; + var31 = 0; + var6 = 0; + + int var21; + int var22; + for (var7 = 0; var7 < var11; ++var7) + { + var22 = var39.readUnsignedByte(); + if (var22 == 1) + { + var18 = var5.readShortSmart() + var6; + var8 = var5.readShortSmart() + var18; + var31 = var5.readShortSmart() + var8; + var6 = var31; + model.faceVertexIndices1[var7] = var18; + model.faceVertexIndices2[var7] = var8; + model.faceVertexIndices3[var7] = var31; + } + + if (var22 == 2) + { + var8 = var31; + var31 = var5.readShortSmart() + var6; + var6 = var31; + model.faceVertexIndices1[var7] = var18; + model.faceVertexIndices2[var7] = var8; + model.faceVertexIndices3[var7] = var31; + } + + if (var22 == 3) + { + var18 = var31; + var31 = var5.readShortSmart() + var6; + var6 = var31; + model.faceVertexIndices1[var7] = var18; + model.faceVertexIndices2[var7] = var8; + model.faceVertexIndices3[var7] = var31; + } + + if (var22 == 4) + { + var21 = var18; + var18 = var8; + var8 = var21; + var31 = var5.readShortSmart() + var6; + var6 = var31; + model.faceVertexIndices1[var7] = var18; + model.faceVertexIndices2[var7] = var21; + model.faceVertexIndices3[var7] = var31; + } + } + + var5.setOffset(var32); + + for (var7 = 0; var7 < var12; ++var7) + { + model.textureRenderTypes[var7] = 0; + model.textureTriangleVertexIndices1[var7] = (short) var5.readUnsignedShort(); + model.textureTriangleVertexIndices2[var7] = (short) var5.readUnsignedShort(); + model.textureTriangleVertexIndices3[var7] = (short) var5.readUnsignedShort(); + } + + if (model.textureCoordinates != null) + { + boolean var45 = false; + + for (var22 = 0; var22 < var11; ++var22) + { + var21 = model.textureCoordinates[var22] & 255; + if (var21 != 255) + { + if ((model.textureTriangleVertexIndices1[var21] & '\uffff') == model.faceVertexIndices1[var22] && (model.textureTriangleVertexIndices2[var21] & '\uffff') == model.faceVertexIndices2[var22] && (model.textureTriangleVertexIndices3[var21] & '\uffff') == model.faceVertexIndices3[var22]) + { + model.textureCoordinates[var22] = -1; + } + else + { + var45 = true; + } + } + } + + if (!var45) + { + model.textureCoordinates = null; + } + } + + if (!var43) + { + model.faceTextures = null; + } + + if (!var2) + { + model.faceRenderTypes = null; + } + } + +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/NpcLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/NpcLoader.java new file mode 100644 index 0000000..0ce81f8 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/NpcLoader.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import java.util.HashMap; +import net.runelite.cache.definitions.NpcDefinition; +import net.runelite.cache.io.InputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NpcLoader +{ + private static final Logger logger = LoggerFactory.getLogger(NpcLoader.class); + + public NpcDefinition load(int id, byte[] b) + { + NpcDefinition def = new NpcDefinition(id); + InputStream is = new InputStream(b); + + while (true) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + this.decodeValues(opcode, def, is); + } + + return def; + } + + private void decodeValues(int opcode, NpcDefinition def, InputStream stream) + { + int length; + int index; + if (opcode == 1) + { + length = stream.readUnsignedByte(); + def.models = new int[length]; + + for (index = 0; index < length; ++index) + { + def.models[index] = stream.readUnsignedShort(); + } + } + else if (opcode == 2) + { + def.name = stream.readString(); + } + else if (opcode == 12) + { + def.size = stream.readUnsignedByte(); + } + else if (opcode == 13) + { + def.standingAnimation = stream.readUnsignedShort(); + } + else if (opcode == 14) + { + def.walkingAnimation = stream.readUnsignedShort(); + } + else if (opcode == 15) + { + def.rotateLeftAnimation = stream.readUnsignedShort(); + } + else if (opcode == 16) + { + def.rotateRightAnimation = stream.readUnsignedShort(); + } + else if (opcode == 17) + { + def.walkingAnimation = stream.readUnsignedShort(); + def.rotate180Animation = stream.readUnsignedShort(); + def.rotate90RightAnimation = stream.readUnsignedShort(); + def.rotate90LeftAnimation = stream.readUnsignedShort(); + } + else if (opcode >= 30 && opcode < 35) + { + def.actions[opcode - 30] = stream.readString(); + if (def.actions[opcode - 30].equalsIgnoreCase("Hidden")) + { + def.actions[opcode - 30] = null; + } + } + else if (opcode == 40) + { + length = stream.readUnsignedByte(); + def.recolorToFind = new short[length]; + def.recolorToReplace = new short[length]; + + for (index = 0; index < length; ++index) + { + def.recolorToFind[index] = (short) stream.readUnsignedShort(); + def.recolorToReplace[index] = (short) stream.readUnsignedShort(); + } + + } + else if (opcode == 41) + { + length = stream.readUnsignedByte(); + def.retextureToFind = new short[length]; + def.retextureToReplace = new short[length]; + + for (index = 0; index < length; ++index) + { + def.retextureToFind[index] = (short) stream.readUnsignedShort(); + def.retextureToReplace[index] = (short) stream.readUnsignedShort(); + } + + } + else if (opcode == 60) + { + length = stream.readUnsignedByte(); + def.chatheadModels = new int[length]; + + for (index = 0; index < length; ++index) + { + def.chatheadModels[index] = stream.readUnsignedShort(); + } + + } + else if (opcode == 93) + { + def.isMinimapVisible = false; + } + else if (opcode == 95) + { + def.combatLevel = stream.readUnsignedShort(); + } + else if (opcode == 97) + { + def.widthScale = stream.readUnsignedShort(); + } + else if (opcode == 98) + { + def.heightScale = stream.readUnsignedShort(); + } + else if (opcode == 99) + { + def.hasRenderPriority = true; + } + else if (opcode == 100) + { + def.ambient = stream.readByte(); + } + else if (opcode == 101) + { + def.contrast = stream.readByte(); + } + else if (opcode == 102) + { + def.headIcon = stream.readUnsignedShort(); + } + else if (opcode == 103) + { + def.rotationSpeed = stream.readUnsignedShort(); + } + else if (opcode == 106) + { + def.varbitId = stream.readUnsignedShort(); + if (def.varbitId == 65535) + { + def.varbitId = -1; + } + + def.varpIndex = stream.readUnsignedShort(); + if (def.varpIndex == 65535) + { + def.varpIndex = -1; + } + + length = stream.readUnsignedByte(); + def.configs = new int[length + 2]; + + for (index = 0; index <= length; ++index) + { + def.configs[index] = stream.readUnsignedShort(); + if (def.configs[index] == '\uffff') + { + def.configs[index] = -1; + } + } + + def.configs[length + 1] = -1; + + } + else if (opcode == 107) + { + def.isInteractable = false; + } + else if (opcode == 109) + { + def.rotationFlag = false; + } + else if (opcode == 111) + { + def.isPet = true; + } + else if (opcode == 118) + { + def.varbitId = stream.readUnsignedShort(); + if (def.varbitId == 65535) + { + def.varbitId = -1; + } + + def.varpIndex = stream.readUnsignedShort(); + if (def.varpIndex == 65535) + { + def.varpIndex = -1; + } + + int var = stream.readUnsignedShort(); + if (var == 0xFFFF) + { + var = -1; + } + + length = stream.readUnsignedByte(); + def.configs = new int[length + 2]; + + for (index = 0; index <= length; ++index) + { + def.configs[index] = stream.readUnsignedShort(); + if (def.configs[index] == '\uffff') + { + def.configs[index] = -1; + } + } + + def.configs[length + 1] = var; + } + else if (opcode == 249) + { + length = stream.readUnsignedByte(); + + def.params = new HashMap<>(length); + + for (int i = 0; i < length; i++) + { + boolean isString = stream.readUnsignedByte() == 1; + int key = stream.read24BitInt(); + Object value; + + if (isString) + { + value = stream.readString(); + } + + else + { + value = stream.readInt(); + } + + def.params.put(key, value); + } + } + else + { + logger.warn("Unrecognized opcode {}", opcode); + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/ObjectLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/ObjectLoader.java new file mode 100644 index 0000000..edd5066 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/ObjectLoader.java @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.ObjectDefinition; +import net.runelite.cache.io.InputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ObjectLoader +{ + private static final Logger logger = LoggerFactory.getLogger(ObjectLoader.class); + + public ObjectDefinition load(int id, byte[] b) + { + ObjectDefinition def = new ObjectDefinition(); + InputStream is = new InputStream(b); + + def.setId(id); + + for (;;) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + processOp(opcode, def, is); + } + + post(def); + + return def; + } + + private void processOp(int opcode, ObjectDefinition def, InputStream is) + { + if (opcode == 1) + { + int length = is.readUnsignedByte(); + if (length > 0) + { + int[] objectTypes = new int[length]; + int[] objectModels = new int[length]; + + for (int index = 0; index < length; ++index) + { + objectModels[index] = is.readUnsignedShort(); + objectTypes[index] = is.readUnsignedByte(); + } + + def.setObjectTypes(objectTypes); + def.setObjectModels(objectModels); + } + } + else if (opcode == 2) + { + def.setName(is.readString()); + } + else if (opcode == 5) + { + int length = is.readUnsignedByte(); + if (length > 0) + { + def.setObjectTypes(null); + int[] objectModels = new int[length]; + + for (int index = 0; index < length; ++index) + { + objectModels[index] = is.readUnsignedShort(); + } + + def.setObjectModels(objectModels); + } + } + else if (opcode == 14) + { + def.setSizeX(is.readUnsignedByte()); + } + else if (opcode == 15) + { + def.setSizeY(is.readUnsignedByte()); + } + else if (opcode == 17) + { + def.setInteractType(0); + def.setBlocksProjectile(false); + } + else if (opcode == 18) + { + def.setBlocksProjectile(false); + } + else if (opcode == 19) + { + def.setWallOrDoor(is.readUnsignedByte()); + } + else if (opcode == 21) + { + def.setContouredGround(0); + } + else if (opcode == 22) + { + def.setMergeNormals(true); + } + else if (opcode == 23) + { + def.setABool2111(true); + } + else if (opcode == 24) + { + def.setAnimationID(is.readUnsignedShort()); + if (def.getAnimationID() == 0xFFFF) + { + def.setAnimationID(-1); + } + } + else if (opcode == 27) + { + def.setInteractType(1); + } + else if (opcode == 28) + { + def.setDecorDisplacement(is.readUnsignedByte()); + } + else if (opcode == 29) + { + def.setAmbient(is.readByte()); + } + else if (opcode == 39) + { + def.setContrast(is.readByte() * 25); + } + else if (opcode >= 30 && opcode < 35) + { + String[] actions = def.getActions(); + actions[opcode - 30] = is.readString(); + if (actions[opcode - 30].equalsIgnoreCase("Hidden")) + { + actions[opcode - 30] = null; + } + } + else if (opcode == 40) + { + int length = is.readUnsignedByte(); + short[] recolorToFind = new short[length]; + short[] recolorToReplace = new short[length]; + + for (int index = 0; index < length; ++index) + { + recolorToFind[index] = is.readShort(); + recolorToReplace[index] = is.readShort(); + } + + def.setRecolorToFind(recolorToFind); + def.setRecolorToReplace(recolorToReplace); + } + else if (opcode == 41) + { + int length = is.readUnsignedByte(); + short[] retextureToFind = new short[length]; + short[] textureToReplace = new short[length]; + + for (int index = 0; index < length; ++index) + { + retextureToFind[index] = is.readShort(); + textureToReplace[index] = is.readShort(); + } + + def.setRetextureToFind(retextureToFind); + def.setTextureToReplace(textureToReplace); + } + else if (opcode == 62) + { + def.setRotated(true); + } + else if (opcode == 64) + { + def.setShadow(false); + } + else if (opcode == 65) + { + def.setModelSizeX(is.readUnsignedShort()); + } + else if (opcode == 66) + { + def.setModelSizeHeight(is.readUnsignedShort()); + } + else if (opcode == 67) + { + def.setModelSizeY(is.readUnsignedShort()); + } + else if (opcode == 68) + { + def.setMapSceneID(is.readUnsignedShort()); + } + else if (opcode == 69) + { + is.readByte(); + } + else if (opcode == 70) + { + def.setOffsetX(is.readUnsignedShort()); + } + else if (opcode == 71) + { + def.setOffsetHeight(is.readUnsignedShort()); + } + else if (opcode == 72) + { + def.setOffsetY(is.readUnsignedShort()); + } + else if (opcode == 73) + { + def.setObstructsGround(true); + } + else if (opcode == 74) + { + def.setHollow(true); + } + else if (opcode == 75) + { + def.setSupportsItems(is.readUnsignedByte()); + } + else if (opcode == 77) + { + int varpID = is.readUnsignedShort(); + if (varpID == 0xFFFF) + { + varpID = -1; + } + def.setVarbitID(varpID); + + int configId = is.readUnsignedShort(); + if (configId == 0xFFFF) + { + configId = -1; + } + def.setVarpID(configId); + + int length = is.readUnsignedByte(); + int[] configChangeDest = new int[length + 2]; + + for (int index = 0; index <= length; ++index) + { + configChangeDest[index] = is.readUnsignedShort(); + if (0xFFFF == configChangeDest[index]) + { + configChangeDest[index] = -1; + } + } + + configChangeDest[length + 1] = -1; + + def.setConfigChangeDest(configChangeDest); + } + else if (opcode == 78) + { + def.setAmbientSoundId(is.readUnsignedShort()); + def.setAnInt2083(is.readUnsignedByte()); + } + else if (opcode == 79) + { + def.setAnInt2112(is.readUnsignedShort()); + def.setAnInt2113(is.readUnsignedShort()); + def.setAnInt2083(is.readUnsignedByte()); + int length = is.readUnsignedByte(); + int[] anIntArray2084 = new int[length]; + + for (int index = 0; index < length; ++index) + { + anIntArray2084[index] = is.readUnsignedShort(); + } + + def.setAnIntArray2084(anIntArray2084); + } + else if (opcode == 81) + { + def.setContouredGround(is.readUnsignedByte() * 256); + } + else if (opcode == 82) + { + def.setMapAreaId(is.readUnsignedShort()); + } + else if (opcode == 92) + { + int varpID = is.readUnsignedShort(); + if (varpID == 0xFFFF) + { + varpID = -1; + } + def.setVarbitID(varpID); + + int configId = is.readUnsignedShort(); + if (configId == 0xFFFF) + { + configId = -1; + } + def.setVarpID(configId); + + + int var = is.readUnsignedShort(); + if (var == 0xFFFF) + { + var = -1; + } + + int length = is.readUnsignedByte(); + int[] configChangeDest = new int[length + 2]; + + for (int index = 0; index <= length; ++index) + { + configChangeDest[index] = is.readUnsignedShort(); + if (0xFFFF == configChangeDest[index]) + { + configChangeDest[index] = -1; + } + } + + configChangeDest[length + 1] = var; + + def.setConfigChangeDest(configChangeDest); + } + else if (opcode == 249) + { + int length = is.readUnsignedByte(); + + Map params = new HashMap<>(length); + for (int i = 0; i < length; i++) + { + boolean isString = is.readUnsignedByte() == 1; + int key = is.read24BitInt(); + Object value; + + if (isString) + { + value = is.readString(); + } + + else + { + value = is.readInt(); + } + + params.put(key, value); + } + + def.setParams(params); + } + else + { + logger.warn("Unrecognized opcode {}", opcode); + } + } + + + private void post(ObjectDefinition def) + { + if (def.getWallOrDoor() == -1) + { + def.setWallOrDoor(0); + if (def.getObjectModels() != null && (def.getObjectTypes() == null || def.getObjectTypes()[0] == 10)) + { + def.setWallOrDoor(1); + } + + for (int var1 = 0; var1 < 5; ++var1) + { + if (def.getActions()[var1] != null) + { + def.setWallOrDoor(1); + } + } + } + + if (def.getSupportsItems() == -1) + { + def.setSupportsItems(def.getInteractType() != 0 ? 1 : 0); + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/OverlayLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/OverlayLoader.java new file mode 100644 index 0000000..1b01c07 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/OverlayLoader.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.OverlayDefinition; +import net.runelite.cache.io.InputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OverlayLoader +{ + private static final Logger logger = LoggerFactory.getLogger(OverlayLoader.class); + + public OverlayDefinition load(int id, byte[] b) + { + OverlayDefinition def = new OverlayDefinition(); + InputStream is = new InputStream(b); + + def.setId(id); + + for (;;) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + if (opcode == 1) + { + int color = is.read24BitInt(); + def.setRgbColor(color); + } + else if (opcode == 2) + { + int texture = is.readUnsignedByte(); + def.setTexture(texture); + } + else if (opcode == 5) + { + def.setHideUnderlay(false); + } + else if (opcode == 7) + { + int secondaryColor = is.read24BitInt(); + def.setSecondaryRgbColor(secondaryColor); + } + } + + def.calculateHsl(); + + return def; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/ParamLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/ParamLoader.java new file mode 100644 index 0000000..9e3ac8f --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/ParamLoader.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.ParamDefinition; +import net.runelite.cache.io.InputStream; +import net.runelite.cache.util.ScriptVarType; + +public class ParamLoader +{ + public ParamDefinition load(byte[] data) + { + ParamDefinition def = new ParamDefinition(); + InputStream b = new InputStream(data); + + for (; ; ) + { + int opcode = b.readUnsignedByte(); + + switch (opcode) + { + case 0: + return def; + case 1: + { + int idx = b.readByte(); + def.setType(ScriptVarType.forCharKey((char) idx)); + break; + } + case 2: + def.setDefaultInt(b.readInt()); + break; + case 4: + def.setMembers(false); + break; + case 5: + def.setDefaultString(b.readString()); + break; + } + } + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/definitions/loaders/ScriptLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/ScriptLoader.java new file mode 100644 index 0000000..923f781 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/ScriptLoader.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.definitions.ScriptDefinition; +import net.runelite.cache.io.InputStream; +import static net.runelite.cache.script.Opcodes.SCONST; +import static net.runelite.cache.script.Opcodes.POP_INT; +import static net.runelite.cache.script.Opcodes.POP_STRING; +import static net.runelite.cache.script.Opcodes.RETURN; + +public class ScriptLoader +{ + public ScriptDefinition load(int id, byte[] b) + { + ScriptDefinition def = new ScriptDefinition(); + def.setId(id); + InputStream in = new InputStream(b); + + in.setOffset(in.getLength() - 2); + int switchLength = in.readUnsignedShort(); + + // 2 for switchLength + the switch data + 12 for the param/vars/stack data + int endIdx = in.getLength() - 2 - switchLength - 12; + in.setOffset(endIdx); + int numOpcodes = in.readInt(); + int localIntCount = in.readUnsignedShort(); + int localStringCount = in.readUnsignedShort(); + int intStackCount = in.readUnsignedShort(); + int stringStackCount = in.readUnsignedShort(); + + int numSwitches = in.readUnsignedByte(); + if (numSwitches > 0) + { + @SuppressWarnings("unchecked") Map[] switches = new Map[numSwitches]; + def.setSwitches(switches); + + for (int i = 0; i < numSwitches; ++i) + { + switches[i] = new HashMap<>(); + + int count = in.readUnsignedShort(); + while (count-- > 0) + { + int key = in.readInt(); // int from stack is compared to this + int pcOffset = in.readInt(); // pc jumps by this + + switches[i].put(key, pcOffset); + } + } + } + + def.setLocalIntCount(localIntCount); + def.setLocalStringCount(localStringCount); + def.setIntStackCount(intStackCount); + def.setStringStackCount(stringStackCount); + + in.setOffset(0); + in.readStringOrNull(); + + int[] instructions = new int[numOpcodes]; + int[] intOperands = new int[numOpcodes]; + String[] stringOperands = new String[numOpcodes]; + + def.setInstructions(instructions); + def.setIntOperands(intOperands); + def.setStringOperands(stringOperands); + + int opcode; + for (int i = 0; in.getOffset() < endIdx; instructions[i++] = opcode) + { + opcode = in.readUnsignedShort(); + if (opcode == SCONST) + { + stringOperands[i] = in.readString(); + } + else if (opcode < 100 && opcode != RETURN && opcode != POP_INT && opcode != POP_STRING) + { + intOperands[i] = in.readInt(); + } + else + { + intOperands[i] = in.readUnsignedByte(); + } + } + + return def; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/SequenceLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/SequenceLoader.java new file mode 100644 index 0000000..987cbd4 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/SequenceLoader.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.SequenceDefinition; +import net.runelite.cache.io.InputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SequenceLoader +{ + private static final Logger logger = LoggerFactory.getLogger(SequenceLoader.class); + + public SequenceDefinition load(int id, byte[] b) + { + SequenceDefinition def = new SequenceDefinition(id); + InputStream is = new InputStream(b); + + while (true) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + this.decodeValues(opcode, def, is); + } + + return def; + } + + private void decodeValues(int opcode, SequenceDefinition def, InputStream stream) + { + int var3; + int var4; + if (opcode == 1) + { + var3 = stream.readUnsignedShort(); + def.frameLenghts = new int[var3]; + + for (var4 = 0; var4 < var3; ++var4) + { + def.frameLenghts[var4] = stream.readUnsignedShort(); + } + + def.frameIDs = new int[var3]; + + for (var4 = 0; var4 < var3; ++var4) + { + def.frameIDs[var4] = stream.readUnsignedShort(); + } + + for (var4 = 0; var4 < var3; ++var4) + { + def.frameIDs[var4] += stream.readUnsignedShort() << 16; + } + } + else if (opcode == 2) + { + def.frameStep = stream.readUnsignedShort(); + } + else if (opcode == 3) + { + var3 = stream.readUnsignedByte(); + def.interleaveLeave = new int[1 + var3]; + + for (var4 = 0; var4 < var3; ++var4) + { + def.interleaveLeave[var4] = stream.readUnsignedByte(); + } + + def.interleaveLeave[var3] = 9999999; + } + else if (opcode == 4) + { + def.stretches = true; + } + else if (opcode == 5) + { + def.forcedPriority = stream.readUnsignedByte(); + } + else if (opcode == 6) + { + def.leftHandItem = stream.readUnsignedShort(); + } + else if (opcode == 7) + { + def.rightHandItem = stream.readUnsignedShort(); + } + else if (opcode == 8) + { + def.maxLoops = stream.readUnsignedByte(); + } + else if (opcode == 9) + { + def.precedenceAnimating = stream.readUnsignedByte(); + } + else if (opcode == 10) + { + def.priority = stream.readUnsignedByte(); + } + else if (opcode == 11) + { + def.replyMode = stream.readUnsignedByte(); + } + else if (opcode == 12) + { + var3 = stream.readUnsignedByte(); + def.field3048 = new int[var3]; + + for (var4 = 0; var4 < var3; ++var4) + { + def.field3048[var4] = stream.readUnsignedShort(); + } + + for (var4 = 0; var4 < var3; ++var4) + { + def.field3048[var4] += stream.readUnsignedShort() << 16; + } + } + else if (opcode == 13) + { + var3 = stream.readUnsignedByte(); + def.field3056 = new int[var3]; + + for (var4 = 0; var4 < var3; ++var4) + { + def.field3056[var4] = stream.read24BitInt(); + } + } + + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/SpotAnimLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/SpotAnimLoader.java new file mode 100644 index 0000000..20f2be2 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/SpotAnimLoader.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.SpotAnimDefinition; +import net.runelite.cache.io.InputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SpotAnimLoader +{ + private static final Logger logger = LoggerFactory.getLogger(SpotAnimLoader.class); + + public SpotAnimDefinition load(int id, byte[] b) + { + SpotAnimDefinition def = new SpotAnimDefinition(); + InputStream is = new InputStream(b); + def.id = id; + + while (true) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + this.decodeValues(opcode, def, is); + } + + return def; + } + + private void decodeValues(int opcode, SpotAnimDefinition def, InputStream stream) + { + if (opcode == 1) + { + def.modelId = stream.readUnsignedShort(); + } + else if (opcode == 2) + { + def.animationId = stream.readUnsignedShort(); + } + else if (opcode == 4) + { + def.resizeX = stream.readUnsignedShort(); + } + else if (opcode == 5) + { + def.resizeY = stream.readUnsignedShort(); + } + else if (opcode == 6) + { + def.rotaton = stream.readUnsignedShort(); + } + else if (opcode == 7) + { + def.ambient = stream.readUnsignedByte(); + } + else if (opcode == 8) + { + def.contrast = stream.readUnsignedByte(); + } + else if (opcode == 40) + { + int var3 = stream.readUnsignedByte(); + def.recolorToFind = new short[var3]; + def.recolorToReplace = new short[var3]; + + for (int var4 = 0; var4 < var3; ++var4) + { + def.recolorToFind[var4] = (short) stream.readUnsignedShort(); + def.recolorToReplace[var4] = (short) stream.readUnsignedShort(); + } + } + else if (opcode == 41) + { + int var3 = stream.readUnsignedByte(); + def.textureToFind = new short[var3]; + def.textureToReplace = new short[var3]; + + for (int var4 = 0; var4 < var3; ++var4) + { + def.textureToFind[var4] = (short) stream.readUnsignedShort(); + def.textureToReplace[var4] = (short) stream.readUnsignedShort(); + } + } + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/SpriteLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/SpriteLoader.java new file mode 100644 index 0000000..9dc6e43 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/SpriteLoader.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.SpriteDefinition; +import net.runelite.cache.io.InputStream; + +public class SpriteLoader +{ + public static final int FLAG_VERTICAL = 0b01; + public static final int FLAG_ALPHA = 0b10; + + public SpriteDefinition[] load(int id, byte[] b) + { + InputStream is = new InputStream(b); + + is.setOffset(is.getLength() - 2); + int spriteCount = is.readUnsignedShort(); + + SpriteDefinition[] sprites = new SpriteDefinition[spriteCount]; + + // 2 for size + // 5 for width, height, palette length + // + 8 bytes per sprite for offset x/y, width, and height + is.setOffset(is.getLength() - 7 - spriteCount * 8); + + // max width and height + int width = is.readUnsignedShort(); + int height = is.readUnsignedShort(); + int paletteLength = is.readUnsignedByte() + 1; + + for (int i = 0; i < spriteCount; ++i) + { + sprites[i] = new SpriteDefinition(); + sprites[i].setId(id); + sprites[i].setFrame(i); + sprites[i].setMaxWidth(width); + sprites[i].setMaxHeight(height); + } + + for (int i = 0; i < spriteCount; ++i) + { + sprites[i].setOffsetX(is.readUnsignedShort()); + } + + for (int i = 0; i < spriteCount; ++i) + { + sprites[i].setOffsetY(is.readUnsignedShort()); + } + + for (int i = 0; i < spriteCount; ++i) + { + sprites[i].setWidth(is.readUnsignedShort()); + } + + for (int i = 0; i < spriteCount; ++i) + { + sprites[i].setHeight(is.readUnsignedShort()); + } + + // same as above + 3 bytes for each palette entry, except for the first one (which is transparent) + is.setOffset(is.getLength() - 7 - spriteCount * 8 - (paletteLength - 1) * 3); + int[] palette = new int[paletteLength]; + + for (int i = 1; i < paletteLength; ++i) + { + palette[i] = is.read24BitInt(); + + if (palette[i] == 0) + { + palette[i] = 1; + } + } + + is.setOffset(0); + + for (int i = 0; i < spriteCount; ++i) + { + SpriteDefinition def = sprites[i]; + int spriteWidth = def.getWidth(); + int spriteHeight = def.getHeight(); + int dimension = spriteWidth * spriteHeight; + byte[] pixelPaletteIndicies = new byte[dimension]; + byte[] pixelAlphas = new byte[dimension]; + def.pixelIdx = pixelPaletteIndicies; + def.palette = palette; + + int flags = is.readUnsignedByte(); + + if ((flags & FLAG_VERTICAL) == 0) + { + // read horizontally + for (int j = 0; j < dimension; ++j) + { + pixelPaletteIndicies[j] = is.readByte(); + } + } + else + { + // read vertically + for (int j = 0; j < spriteWidth; ++j) + { + for (int k = 0; k < spriteHeight; ++k) + { + pixelPaletteIndicies[spriteWidth * k + j] = is.readByte(); + } + } + } + + // read alphas + if ((flags & FLAG_ALPHA) != 0) + { + if ((flags & FLAG_VERTICAL) == 0) + { + // read horizontally + for (int j = 0; j < dimension; ++j) + { + pixelAlphas[j] = is.readByte(); + } + } + else + { + // read vertically + for (int j = 0; j < spriteWidth; ++j) + { + for (int k = 0; k < spriteHeight; ++k) + { + pixelAlphas[spriteWidth * k + j] = is.readByte(); + } + } + } + } + else + { + // everything non-zero is opaque + for (int j = 0; j < dimension; ++j) + { + int index = pixelPaletteIndicies[j]; + + if (index != 0) + pixelAlphas[j] = (byte) 0xFF; + } + } + + int[] pixels = new int[dimension]; + + // build argb pixels from palette/alphas + for (int j = 0; j < dimension; ++j) + { + int index = pixelPaletteIndicies[j] & 0xFF; + + pixels[j] = palette[index] | (pixelAlphas[j] << 24); + } + + def.setPixels(pixels); + } + + return sprites; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/StructLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/StructLoader.java new file mode 100644 index 0000000..4137da8 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/StructLoader.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, Joshua Filby + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import java.util.HashMap; +import net.runelite.cache.definitions.StructDefinition; +import net.runelite.cache.io.InputStream; + +public class StructLoader +{ + public StructDefinition load(int id, byte[] b) + { + StructDefinition def = new StructDefinition(id); + InputStream is = new InputStream(b); + + while (true) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + this.decodeValues(opcode, def, is); + } + + return def; + } + + private void decodeValues(int opcode, StructDefinition def, InputStream stream) + { + if (opcode == 249) + { + int length = stream.readUnsignedByte(); + + def.params = new HashMap<>(length); + + for (int i = 0; i < length; i++) + { + boolean isString = stream.readUnsignedByte() == 1; + int key = stream.read24BitInt(); + Object value; + + if (isString) + { + value = stream.readString(); + } + else + { + value = stream.readInt(); + } + + def.params.put(key, value); + } + } + } + +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/TextureLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/TextureLoader.java new file mode 100644 index 0000000..3e9ff09 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/TextureLoader.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.TextureDefinition; +import net.runelite.cache.io.InputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TextureLoader +{ + private static final Logger logger = LoggerFactory.getLogger(TextureLoader.class); + + public TextureDefinition load(int id, byte[] b) + { + TextureDefinition def = new TextureDefinition(); + InputStream is = new InputStream(b); + + def.field1777 = is.readUnsignedShort(); + def.field1778 = is.readByte() != 0; + def.setId(id); + + int count = is.readUnsignedByte(); + int[] files = new int[count]; + + for (int i = 0; i < count; ++i) + files[i] = is.readUnsignedShort(); + + def.setFileIds(files); + + if (count > 1) + { + def.field1780 = new int[count - 1]; + + for (int var3 = 0; var3 < count - 1; ++var3) + { + def.field1780[var3] = is.readUnsignedByte(); + } + } + + if (count > 1) + { + def.field1781 = new int[count - 1]; + + for (int var3 = 0; var3 < count - 1; ++var3) + { + def.field1781[var3] = is.readUnsignedByte(); + } + } + + def.field1786 = new int[count]; + + for (int var3 = 0; var3 < count; ++var3) + { + def.field1786[var3] = is.readInt(); + } + + def.field1783 = is.readUnsignedByte(); + def.field1782 = is.readUnsignedByte(); + + return def; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/TrackLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/TrackLoader.java new file mode 100644 index 0000000..6911b9d --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/TrackLoader.java @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.TrackDefinition; +import net.runelite.cache.io.InputStream; +import net.runelite.cache.io.OutputStream; + +public class TrackLoader +{ + // Headers + private static final int MTHD_MAGIC = 1297377380; + private static final int MTRK_MAGIC = 1297379947; + + // Major MIDI Messages. Bottom 4 bits are the channel. + private static final int NOTE_ON = 0b1001_0000; + private static final int NOTE_OFF = 0b1000_0000; + private static final int CONTROL_CHANGE = 0b1011_0000; + private static final int PITCH_WHEEL_CHANGE = 0b1110_0000; + private static final int CHANNEL_PRESSURE = 0b1101_0000; + private static final int POLYPHONIC_KEY_PRESSURE = 0b1010_0000; + private static final int PROGRAM_CHANGE = 0b1100_0000; + + // Meta Events + private static final int META = 255; + private static final int END_OF_TRACK = 47; + private static final int TEMPO = 81; + + // Controller messages + private static final int CONTROLLER_BANK_SELECT = 0; + private static final int CONTROLLER_MODULATION_WHEEL = 1; + private static final int CONTROLLER_CHANNEL_VOLUME = 7; + private static final int CONTROLLER_PAN = 10; + private static final int CONTROLLER_BANK_SELECT_2 = 32; + private static final int CONTROLLER_MODULATION_WHEEL2 = 33; + private static final int CONTROLLER_CHANNEL_VOLUME_2 = 39; + private static final int CONTROLLER_PAN_2 = 42; + private static final int CONTROLLER_DAMPER_PEDAL = 64; + private static final int CONTROLLER_PORTAMENTO = 65; + private static final int CONTROLLER_NON_REGISTERED_PARAMETER_NUMBER_LSB = 98; + private static final int CONTROLLER_NON_REGISTERED_PARAMETER_NUMBER_MSB = 99; + private static final int CONTROLLER_REGISTERED_PARAMETER_NUMBER_LSB = 100; + private static final int CONTROLLER_REGISTERED_PARAMETER_NUMBER_MSB = 101; + private static final int CONTROLLER_ALL_SOUND_OFF = 120; + private static final int CONTROLLER_RESET_ALL_CONTROLLERS = 121; + private static final int CONTROLLER_ALL_NOTES_OFF = 123; + + private static final int JAG_NOTE_ON = 0; + private static final int JAG_NOTE_OFF = 1; + private static final int JAG_CONTROL_CHANGE = 2; + private static final int JAG_PITCH_BEND = 3; + private static final int JAG_CHANNEL_PRESSURE = 4; + private static final int JAG_POLY_PRESSURE = 5; + private static final int JAG_PROGRAM_CHANGE = 6; + private static final int JAG_END_OF_TRACK = 7; + private static final int JAG_TEMPO = 23; + + public TrackDefinition load(byte[] b) + { + TrackDefinition def = new TrackDefinition(); + load(def, new InputStream(b)); + return def; + } + + private void load(TrackDefinition def, InputStream var1) + { + // Some of the names are from https://www.rune-server.ee/runescape-development/rs-503-client-server/snippets/311669-rs-music-file-structure-conversion.html + var1.setOffset(var1.getLength() - 3); + int tracks = var1.readUnsignedByte(); + int division = var1.readUnsignedShort(); + int offset = 14 + tracks * 10; + var1.setOffset(0); + int tempoOpcodes = 0; + int ctrlChangeOpcodes = 0; + int noteOnOpcodes = 0; + int noteOffOpcodes = 0; + int wheelChangeOpcodes = 0; + int chnnlAfterTchOpcodes = 0; + int keyAfterTchOpcodes = 0; + int progmChangeOpcodes = 0; + + int var13; + int opcode; + int controlChangeIndex; + for (var13 = 0; var13 < tracks; ++var13) + { + opcode = -1; + + while (true) + { + controlChangeIndex = var1.readUnsignedByte(); + if (controlChangeIndex != opcode) + { + ++offset; + } + + opcode = controlChangeIndex & 15; + if (controlChangeIndex == JAG_END_OF_TRACK) + { + break; + } + + if (controlChangeIndex == JAG_TEMPO) + { + ++tempoOpcodes; + } + else if (opcode == JAG_NOTE_ON) + { + ++noteOnOpcodes; + } + else if (opcode == JAG_NOTE_OFF) + { + ++noteOffOpcodes; + } + else if (opcode == JAG_CONTROL_CHANGE) + { + ++ctrlChangeOpcodes; + } + else if (opcode == JAG_PITCH_BEND) + { + ++wheelChangeOpcodes; + } + else if (opcode == JAG_CHANNEL_PRESSURE) + { + ++chnnlAfterTchOpcodes; + } + else if (opcode == JAG_POLY_PRESSURE) + { + ++keyAfterTchOpcodes; + } + else if (opcode == JAG_PROGRAM_CHANGE) + { + ++progmChangeOpcodes; + } + else + { + throw new RuntimeException(); + } + } + } + + offset += 5 * tempoOpcodes; + offset += 2 * (noteOnOpcodes + noteOffOpcodes + ctrlChangeOpcodes + wheelChangeOpcodes + keyAfterTchOpcodes); + offset += chnnlAfterTchOpcodes + progmChangeOpcodes; + var13 = var1.getOffset(); + opcode = tracks + tempoOpcodes + ctrlChangeOpcodes + noteOnOpcodes + noteOffOpcodes + wheelChangeOpcodes + chnnlAfterTchOpcodes + keyAfterTchOpcodes + progmChangeOpcodes; + + for (controlChangeIndex = 0; controlChangeIndex < opcode; ++controlChangeIndex) + { + var1.readVarInt(); + } + + offset += var1.getOffset() - var13; + controlChangeIndex = var1.getOffset(); + int modulationWheelSize = 0; + int modulationWheel2Size = 0; + int channelVolumeSize = 0; + int channelVolume2Size = 0; + int panSize = 0; + int pan2Size = 0; + int nonRegisteredMsbSize = 0; + int nonRegisteredLsbSize = 0; + int registeredNumberMsb = 0; + int registeredLsbSize = 0; + int commandsSize = 0; + int otherSize = 0; + int controllerNumber = 0; + + int var29; + for (var29 = 0; var29 < ctrlChangeOpcodes; ++var29) + { + controllerNumber = controllerNumber + var1.readUnsignedByte() & 127; + if (controllerNumber == CONTROLLER_BANK_SELECT || controllerNumber == CONTROLLER_BANK_SELECT_2) + { + ++progmChangeOpcodes; + } + else if (controllerNumber == CONTROLLER_MODULATION_WHEEL) + { + ++modulationWheelSize; + } + else if (controllerNumber == CONTROLLER_MODULATION_WHEEL2) + { + ++modulationWheel2Size; + } + else if (controllerNumber == CONTROLLER_CHANNEL_VOLUME) + { + ++channelVolumeSize; + } + else if (controllerNumber == CONTROLLER_CHANNEL_VOLUME_2) + { + ++channelVolume2Size; + } + else if (controllerNumber == CONTROLLER_PAN) + { + ++panSize; + } + else if (controllerNumber == CONTROLLER_PAN_2) + { + ++pan2Size; + } + else if (controllerNumber == CONTROLLER_NON_REGISTERED_PARAMETER_NUMBER_MSB) + { + ++nonRegisteredMsbSize; + } + else if (controllerNumber == CONTROLLER_NON_REGISTERED_PARAMETER_NUMBER_LSB) + { + ++nonRegisteredLsbSize; + } + else if (controllerNumber == CONTROLLER_REGISTERED_PARAMETER_NUMBER_MSB) + { + ++registeredNumberMsb; + } + else if (controllerNumber == CONTROLLER_REGISTERED_PARAMETER_NUMBER_LSB) + { + ++registeredLsbSize; + } + else if (controllerNumber != CONTROLLER_DAMPER_PEDAL + && controllerNumber != CONTROLLER_PORTAMENTO + && controllerNumber != CONTROLLER_ALL_SOUND_OFF + && controllerNumber != CONTROLLER_RESET_ALL_CONTROLLERS + && controllerNumber != CONTROLLER_ALL_NOTES_OFF) + { + ++otherSize; + } + else + { + ++commandsSize; + } + } + + var29 = 0; + int commandsIndex = var1.getOffset(); + var1.skip(commandsSize); + int polyPressureIndex = var1.getOffset(); + var1.skip(keyAfterTchOpcodes); + int channelPressureIndex = var1.getOffset(); + var1.skip(chnnlAfterTchOpcodes); + int pitchWheelHighIndex = var1.getOffset(); + var1.skip(wheelChangeOpcodes); + int modulationWheelOffset = var1.getOffset(); + var1.skip(modulationWheelSize); + int channelVolumeOffset = var1.getOffset(); + var1.skip(channelVolumeSize); + int panOffset = var1.getOffset(); + var1.skip(panSize); + int notesIndex = var1.getOffset(); + var1.skip(noteOnOpcodes + noteOffOpcodes + keyAfterTchOpcodes); + int notesOnIndex = var1.getOffset(); + var1.skip(noteOnOpcodes); + int otherIndex = var1.getOffset(); + var1.skip(otherSize); + int notesOffIndex = var1.getOffset(); + var1.skip(noteOffOpcodes); + int modulationWheel2Offset = var1.getOffset(); + var1.skip(modulationWheel2Size); + int channelVolume2Offset = var1.getOffset(); + var1.skip(channelVolume2Size); + int pan2Offset = var1.getOffset(); + var1.skip(pan2Size); + int programChangeIndex = var1.getOffset(); + var1.skip(progmChangeOpcodes); + int pitchWheelLowIndex = var1.getOffset(); + var1.skip(wheelChangeOpcodes); + int nonRegisteredMsbIndex = var1.getOffset(); + var1.skip(nonRegisteredMsbSize); + int nonRegisteredLsbIndex = var1.getOffset(); + var1.skip(nonRegisteredLsbSize); + int registeredMsbIndex = var1.getOffset(); + var1.skip(registeredNumberMsb); + int registeredLsbIndex = var1.getOffset(); + var1.skip(registeredLsbSize); + int tempoOffset = var1.getOffset(); + var1.skip(tempoOpcodes * 3); + OutputStream var51 = new OutputStream(offset); + var51.writeInt(MTHD_MAGIC); // MThd header + var51.writeInt(6); // length of header + var51.writeShort(tracks > 1 ? 1 : 0); // format + var51.writeShort(tracks); // tracks + var51.writeShort(division); // division + var1.setOffset(var13); + int channel = 0; + int var53 = 0; + int var54 = 0; + int var55 = 0; + int var56 = 0; + int var57 = 0; + int var58 = 0; + int[] var59 = new int[128]; + controllerNumber = 0; + + label361: + for (int var60 = 0; var60 < tracks; ++var60) + { + var51.writeInt(MTRK_MAGIC); // MTrk + var51.skip(4); // length gets written here later + int var61 = var51.getOffset(); + int var62 = -1; + + while (true) + { + int deltaTick = var1.readVarInt(); + var51.writeVarInt(deltaTick); // delta time + int status = var1.getArray()[var29++] & 255; + boolean var65 = status != var62; + var62 = status & 15; + if (status == JAG_END_OF_TRACK) + { + //if (var65) -- client has this if, but it causes broken midi to be produced + { + var51.writeByte(META); + } + + var51.writeByte(END_OF_TRACK); // type - end of track + var51.writeByte(0); // length + var51.writeLengthFromMark(var51.getOffset() - var61); + continue label361; + } + + if (status == JAG_TEMPO) + { + //if (var65) -- client has this if, but it causes broken midi to be produced + { + var51.writeByte(META); // meta event FF + } + + var51.writeByte(TEMPO); // type - set tempo + var51.writeByte(3); // length + var51.writeByte(var1.getArray()[tempoOffset++]); + var51.writeByte(var1.getArray()[tempoOffset++]); + var51.writeByte(var1.getArray()[tempoOffset++]); + } + else + { + channel ^= status >> 4; + if (var62 == JAG_NOTE_ON) + { + if (var65) + { + var51.writeByte(NOTE_ON + channel); + } + + var53 += var1.getArray()[notesIndex++]; + var54 += var1.getArray()[notesOnIndex++]; + var51.writeByte(var53 & 127); + var51.writeByte(var54 & 127); + } + else if (var62 == JAG_NOTE_OFF) + { + if (var65) + { + var51.writeByte(NOTE_OFF + channel); + } + + var53 += var1.getArray()[notesIndex++]; + var55 += var1.getArray()[notesOffIndex++]; + var51.writeByte(var53 & 127); + var51.writeByte(var55 & 127); + } + else if (var62 == JAG_CONTROL_CHANGE) + { + if (var65) + { + var51.writeByte(CONTROL_CHANGE + channel); + } + + controllerNumber = controllerNumber + var1.getArray()[controlChangeIndex++] & 127; + var51.writeByte(controllerNumber); + byte var66; + if (controllerNumber == CONTROLLER_BANK_SELECT || controllerNumber == CONTROLLER_BANK_SELECT_2) + { + var66 = var1.getArray()[programChangeIndex++]; + } + else if (controllerNumber == CONTROLLER_MODULATION_WHEEL) + { + var66 = var1.getArray()[modulationWheelOffset++]; + } + else if (controllerNumber == CONTROLLER_MODULATION_WHEEL2) + { + var66 = var1.getArray()[modulationWheel2Offset++]; + } + else if (controllerNumber == CONTROLLER_CHANNEL_VOLUME) + { + var66 = var1.getArray()[channelVolumeOffset++]; + } + else if (controllerNumber == CONTROLLER_CHANNEL_VOLUME_2) + { + var66 = var1.getArray()[channelVolume2Offset++]; + } + else if (controllerNumber == CONTROLLER_PAN) + { + var66 = var1.getArray()[panOffset++]; + } + else if (controllerNumber == CONTROLLER_PAN_2) + { + var66 = var1.getArray()[pan2Offset++]; + } + else if (controllerNumber == CONTROLLER_NON_REGISTERED_PARAMETER_NUMBER_MSB) + { + var66 = var1.getArray()[nonRegisteredMsbIndex++]; + } + else if (controllerNumber == CONTROLLER_NON_REGISTERED_PARAMETER_NUMBER_LSB) + { + var66 = var1.getArray()[nonRegisteredLsbIndex++]; + } + else if (controllerNumber == CONTROLLER_REGISTERED_PARAMETER_NUMBER_MSB) + { + var66 = var1.getArray()[registeredMsbIndex++]; + } + else if (controllerNumber == CONTROLLER_REGISTERED_PARAMETER_NUMBER_LSB) + { + var66 = var1.getArray()[registeredLsbIndex++]; + } + else if (controllerNumber != CONTROLLER_DAMPER_PEDAL + && controllerNumber != CONTROLLER_PORTAMENTO + && controllerNumber != CONTROLLER_ALL_SOUND_OFF + && controllerNumber != CONTROLLER_RESET_ALL_CONTROLLERS + && controllerNumber != CONTROLLER_ALL_NOTES_OFF) + { + var66 = var1.getArray()[otherIndex++]; + } + else + { + var66 = var1.getArray()[commandsIndex++]; + } + + int var67 = var66 + var59[controllerNumber]; + var59[controllerNumber] = var67; + var51.writeByte(var67 & 127); + } + else if (var62 == JAG_PITCH_BEND) + { + if (var65) + { + var51.writeByte(PITCH_WHEEL_CHANGE + channel); + } + + var56 += var1.getArray()[pitchWheelLowIndex++]; + var56 += var1.getArray()[pitchWheelHighIndex++] << 7; + var51.writeByte(var56 & 127); + var51.writeByte(var56 >> 7 & 127); + } + else if (var62 == JAG_CHANNEL_PRESSURE) + { + if (var65) + { + var51.writeByte(CHANNEL_PRESSURE + channel); + } + + var57 += var1.getArray()[channelPressureIndex++]; + var51.writeByte(var57 & 127); + } + else if (var62 == JAG_POLY_PRESSURE) + { + if (var65) + { + var51.writeByte(POLYPHONIC_KEY_PRESSURE + channel); + } + + var53 += var1.getArray()[notesIndex++]; + var58 += var1.getArray()[polyPressureIndex++]; + var51.writeByte(var53 & 127); + var51.writeByte(var58 & 127); + } + else if (var62 == JAG_PROGRAM_CHANGE) + { + + if (var65) + { + var51.writeByte(PROGRAM_CHANGE + channel); + } + + var51.writeByte(var1.getArray()[programChangeIndex++]); + } + else + { + throw new RuntimeException(); + } + } + } + } + + def.midi = var51.flip(); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/UnderlayLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/UnderlayLoader.java new file mode 100644 index 0000000..5c4c10f --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/UnderlayLoader.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.UnderlayDefinition; +import net.runelite.cache.io.InputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UnderlayLoader +{ + private static final Logger logger = LoggerFactory.getLogger(UnderlayLoader.class); + + public UnderlayDefinition load(int id, byte[] b) + { + UnderlayDefinition def = new UnderlayDefinition(); + InputStream is = new InputStream(b); + + def.setId(id); + + for (;;) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + if (opcode == 1) + { + int color = is.read24BitInt(); + def.setColor(color); + } + } + + def.calculateHsl(); + + return def; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/VarbitLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/VarbitLoader.java new file mode 100644 index 0000000..05d91af --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/VarbitLoader.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.VarbitDefinition; +import net.runelite.cache.io.InputStream; + +public class VarbitLoader +{ + public VarbitDefinition load(int id, byte[] b) + { + VarbitDefinition def = new VarbitDefinition(); + InputStream is = new InputStream(b); + + def.setId(id); + + for (;;) + { + int opcode = is.readUnsignedByte(); + if (opcode == 0) + { + break; + } + + if (opcode == 1) + { + def.setIndex(is.readUnsignedShort()); + def.setLeastSignificantBit(is.readUnsignedByte()); + def.setMostSignificantBit(is.readUnsignedByte()); + } + } + + return def; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/WorldMapLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/WorldMapLoader.java new file mode 100644 index 0000000..3ce0bf4 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/WorldMapLoader.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import java.util.LinkedList; +import net.runelite.cache.definitions.WorldMapDefinition; +import net.runelite.cache.definitions.WorldMapType0; +import net.runelite.cache.definitions.WorldMapType1; +import net.runelite.cache.definitions.WorldMapType2; +import net.runelite.cache.definitions.WorldMapType3; +import net.runelite.cache.definitions.WorldMapTypeBase; +import net.runelite.cache.io.InputStream; +import net.runelite.cache.region.Position; + +public class WorldMapLoader +{ + @SuppressWarnings("unchecked") + public WorldMapDefinition load(byte[] b, int fileId) + { + WorldMapDefinition def = new WorldMapDefinition(); + InputStream in = new InputStream(b); + + def.fileId = fileId; + def.safeName = in.readString(); + def.name = in.readString(); + + int packedPos = in.readInt(); + if (packedPos == -1) + { + def.position = new Position(-1, -1, -1); + } + else + { + int y = packedPos >> 28 & 3; + int x = packedPos >> 14 & 16383; + int z = packedPos & 16383; + def.position = new Position(x, y, z); + } + + def.field450 = in.readInt(); + in.readUnsignedByte(); + def.field457 = in.readUnsignedByte() == 1; + def.field451 = in.readUnsignedByte(); + int var3 = in.readUnsignedByte(); + def.field458 = new LinkedList(); + + for (int var4 = 0; var4 < var3; ++var4) + { + def.field458.add(this.loadType(in)); + } + + return def; + } + + private WorldMapTypeBase loadType(InputStream var1) + { + int var2 = var1.readUnsignedByte(); + // field397 = new class27(1, (byte)0); + // field390 = new class27(2, (byte)1); + // field399 = new class27(3, (byte)2); + // field393 = new class27(0, (byte)3); + WorldMapTypeBase base; + switch (var2) + { + case 0: + // type 1 + base = load1(var1); + break; + case 1: + // type 2 + base = load2(var1); + break; + case 2: + // type 3 + base = load3(var1); + break; + case 3: + // type 0 + base = load0(var1); + break; + default: + throw new IllegalStateException(); + } + return base; + } + + private WorldMapTypeBase load0(InputStream in) + { + WorldMapType0 wm = new WorldMapType0(); + + wm.field606 = in.readUnsignedByte(); + wm.field605 = in.readUnsignedByte(); + wm.field601 = in.readUnsignedShort(); + wm.field602 = in.readUnsignedByte(); + wm.field603 = in.readUnsignedShort(); + wm.field607 = in.readUnsignedByte(); + wm.field604 = in.readUnsignedShort(); + wm.field600 = in.readUnsignedByte(); + wm.field608 = in.readUnsignedShort(); + wm.field609 = in.readUnsignedByte(); + + return wm; + } + + private WorldMapTypeBase load1(InputStream in) + { + WorldMapType1 wm = new WorldMapType1(); + + wm.field434 = in.readUnsignedByte(); + wm.field424 = in.readUnsignedByte(); + wm.field425 = in.readUnsignedShort(); + wm.field426 = in.readUnsignedShort(); + wm.field427 = in.readUnsignedShort(); + wm.field431 = in.readUnsignedShort(); + wm.field429 = in.readUnsignedShort(); + wm.field428 = in.readUnsignedShort(); + wm.field433 = in.readUnsignedShort(); + wm.field435 = in.readUnsignedShort(); + + return wm; + } + + private WorldMapTypeBase load2(InputStream in) + { + WorldMapType2 wm = new WorldMapType2(); + + wm.field519 = in.readUnsignedByte(); + wm.field511 = in.readUnsignedByte(); + wm.field510 = in.readUnsignedShort(); + wm.field512 = in.readUnsignedShort(); + wm.field514 = in.readUnsignedShort(); + wm.field515 = in.readUnsignedShort(); + + return wm; + } + + private WorldMapTypeBase load3(InputStream in) + { + WorldMapType3 wm = new WorldMapType3(); + + wm.field387 = in.readUnsignedByte(); + wm.field377 = in.readUnsignedByte(); + wm.field378 = in.readUnsignedShort(); + wm.field382 = in.readUnsignedByte(); + wm.field376 = in.readUnsignedByte(); + wm.field383 = in.readUnsignedShort(); + wm.field385 = in.readUnsignedByte(); + wm.field379 = in.readUnsignedByte(); + wm.field380 = in.readUnsignedShort(); + wm.field386 = in.readUnsignedByte(); + wm.field388 = in.readUnsignedByte(); + wm.field381 = in.readUnsignedShort(); + wm.field384 = in.readUnsignedByte(); + wm.field389 = in.readUnsignedByte(); + + return wm; + } +} diff --git a/src/main/java/net/runelite/cache/definitions/loaders/sound/AudioEnvelopeLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/sound/AudioEnvelopeLoader.java new file mode 100644 index 0000000..084a8a9 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/sound/AudioEnvelopeLoader.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders.sound; + +import net.runelite.cache.definitions.sound.AudioEnvelopeDefinition; +import net.runelite.cache.io.InputStream; + +public class AudioEnvelopeLoader +{ + public AudioEnvelopeDefinition load(InputStream in) + { + AudioEnvelopeDefinition audioEnvelope = new AudioEnvelopeDefinition(); + + load(audioEnvelope, in); + + return audioEnvelope; + } + + private void load(AudioEnvelopeDefinition audioEnvelope, InputStream in) + { + audioEnvelope.form = in.readUnsignedByte(); + audioEnvelope.start = in.readInt(); + audioEnvelope.end = in.readInt(); + this.loadSegments(audioEnvelope, in); + } + + final void loadSegments(AudioEnvelopeDefinition audioEnvelope, InputStream in) + { + audioEnvelope.segments = in.readUnsignedByte(); + audioEnvelope.durations = new int[audioEnvelope.segments]; + audioEnvelope.phases = new int[audioEnvelope.segments]; + + for (int i = 0; i < audioEnvelope.segments; ++i) + { + audioEnvelope.durations[i] = in.readUnsignedShort(); + audioEnvelope.phases[i] = in.readUnsignedShort(); + } + + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/definitions/loaders/sound/InstrumentLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/sound/InstrumentLoader.java new file mode 100644 index 0000000..f3d2326 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/sound/InstrumentLoader.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders.sound; + +import net.runelite.cache.definitions.sound.InstrumentDefinition; +import net.runelite.cache.definitions.sound.AudioEnvelopeDefinition; +import net.runelite.cache.io.InputStream; + +public class InstrumentLoader +{ + private final AudioEnvelopeLoader aeLoader = new AudioEnvelopeLoader(); + private final SoundEffectLoader seLoader = new SoundEffectLoader(); + + public InstrumentDefinition load(InputStream in) + { + InstrumentDefinition instrument = new InstrumentDefinition(); + + load(instrument, in); + + return instrument; + } + + private void load(InstrumentDefinition instrument, InputStream in) + { + instrument.pitch = aeLoader.load(in); + instrument.volume = aeLoader.load(in); + int volume = in.readUnsignedByte(); + if (volume != 0) + { + in.setOffset(in.getOffset() - 1); + instrument.pitchModifier = aeLoader.load(in); + instrument.pitchModifierAmplitude = aeLoader.load(in); + } + + volume = in.readUnsignedByte(); + if (volume != 0) + { + in.setOffset(in.getOffset() - 1); + instrument.volumeMultiplier = aeLoader.load(in); + instrument.volumeMultiplierAmplitude = aeLoader.load(in); + } + + volume = in.readUnsignedByte(); + if (volume != 0) + { + in.setOffset(in.getOffset() - 1); + instrument.release = aeLoader.load(in); + instrument.field1175 = aeLoader.load(in); + } + + for (int i = 0; i < 10; ++i) + { + int vol = in.readUnsignedShortSmart(); + if (vol == 0) + { + break; + } + + instrument.oscillatorVolume[i] = vol; + instrument.oscillatorPitch[i] = in.readShortSmart(); + instrument.oscillatorDelays[i] = in.readUnsignedShortSmart(); + } + + instrument.delayTime = in.readUnsignedShortSmart(); + instrument.delayDecay = in.readUnsignedShortSmart(); + instrument.duration = in.readUnsignedShort(); + instrument.offset = in.readUnsignedShort(); + instrument.filterEnvelope = new AudioEnvelopeDefinition(); + instrument.filter = seLoader.load(in, instrument.filterEnvelope); + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectLoader.java new file mode 100644 index 0000000..2ee518d --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectLoader.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders.sound; + +import net.runelite.cache.definitions.sound.AudioEnvelopeDefinition; +import net.runelite.cache.definitions.sound.SoundEffectDefinition; +import net.runelite.cache.io.InputStream; + +public class SoundEffectLoader +{ + private final AudioEnvelopeLoader audioEnvelopeLoader = new AudioEnvelopeLoader(); + + public SoundEffectDefinition load(InputStream in, AudioEnvelopeDefinition audioEnvelope) + { + SoundEffectDefinition soundEffect = new SoundEffectDefinition(); + + load(soundEffect, audioEnvelope, in); + + return soundEffect; + } + + private void load(SoundEffectDefinition soundEffect, AudioEnvelopeDefinition audioEnvelope, InputStream in) + { + int id = in.readUnsignedByte(); + soundEffect.pairs[0] = id >> 4; + soundEffect.pairs[1] = id & 15; + if (id != 0) + { + soundEffect.unity[0] = in.readUnsignedShort(); + soundEffect.unity[1] = in.readUnsignedShort(); + int track = in.readUnsignedByte(); + + for (int i = 0; i < 2; ++i) + { + for (int j = 0; j < soundEffect.pairs[i]; ++j) + { + soundEffect.phases[i][0][j] = in.readUnsignedShort(); + soundEffect.magnitudes[i][0][j] = in.readUnsignedShort(); + } + } + + for (int i = 0; i < 2; ++i) + { + for (int j = 0; j < soundEffect.pairs[i]; ++j) + { + if ((track & 1 << i * 4 << j) != 0) + { + soundEffect.phases[i][1][j] = in.readUnsignedShort(); + soundEffect.magnitudes[i][1][j] = in.readUnsignedShort(); + } + else + { + soundEffect.phases[i][1][j] = soundEffect.phases[i][0][j]; + soundEffect.magnitudes[i][1][j] = soundEffect.magnitudes[i][0][j]; + } + } + } + + if (track != 0 || soundEffect.unity[1] != soundEffect.unity[0]) + { + audioEnvelopeLoader.loadSegments(audioEnvelope, in); + } + } + else + { + int[] clean = soundEffect.unity; + soundEffect.unity[1] = 0; + clean[0] = 0; + } + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectTrackLoader.java b/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectTrackLoader.java new file mode 100644 index 0000000..3b991fd --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectTrackLoader.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders.sound; + +import net.runelite.cache.definitions.sound.SoundEffectTrackDefinition; +import net.runelite.cache.definitions.sound.InstrumentDefinition; +import net.runelite.cache.io.InputStream; + +public class SoundEffectTrackLoader +{ + public SoundEffectTrackDefinition load(byte[] b) + { + SoundEffectTrackDefinition soundEffect = new SoundEffectTrackDefinition(); + InputStream in = new InputStream(b); + + load(soundEffect, in); + + return soundEffect; + } + + private void load(SoundEffectTrackDefinition soundEffect, InputStream in) + { + for (int i = 0; i < 10; ++i) + { + int volume = in.readUnsignedByte(); + if (volume != 0) + { + in.setOffset(in.getOffset() - 1); + + InstrumentLoader instrumentLoader = new InstrumentLoader(); + InstrumentDefinition instrument = instrumentLoader.load(in); + + soundEffect.instruments[i] = instrument; + } + } + + soundEffect.start = in.readUnsignedShort(); + soundEffect.end = in.readUnsignedShort(); + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/definitions/providers/ItemProvider.java b/src/main/java/net/runelite/cache/definitions/providers/ItemProvider.java new file mode 100644 index 0000000..7d58c98 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/providers/ItemProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.providers; + +import net.runelite.cache.definitions.ItemDefinition; + +public interface ItemProvider +{ + ItemDefinition provide(int itemId); +} diff --git a/src/main/java/net/runelite/cache/definitions/providers/ModelProvider.java b/src/main/java/net/runelite/cache/definitions/providers/ModelProvider.java new file mode 100644 index 0000000..36a8412 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/providers/ModelProvider.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.providers; + +import java.io.IOException; +import net.runelite.cache.definitions.ModelDefinition; + +public interface ModelProvider +{ + ModelDefinition provide(int modelId) throws IOException; +} diff --git a/src/main/java/net/runelite/cache/definitions/providers/OverlayProvider.java b/src/main/java/net/runelite/cache/definitions/providers/OverlayProvider.java new file mode 100644 index 0000000..a793b39 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/providers/OverlayProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.providers; + +import net.runelite.cache.definitions.OverlayDefinition; + +public interface OverlayProvider +{ + OverlayDefinition provide(int overlayId); +} diff --git a/src/main/java/net/runelite/cache/definitions/providers/SpriteProvider.java b/src/main/java/net/runelite/cache/definitions/providers/SpriteProvider.java new file mode 100644 index 0000000..f7177bd --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/providers/SpriteProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.providers; + +import net.runelite.cache.definitions.SpriteDefinition; + +public interface SpriteProvider +{ + SpriteDefinition provide(int spriteId, int frameId); +} diff --git a/src/main/java/net/runelite/cache/definitions/providers/StructProvider.java b/src/main/java/net/runelite/cache/definitions/providers/StructProvider.java new file mode 100644 index 0000000..54d0306 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/providers/StructProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, Joshua Filby + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.providers; + +import net.runelite.cache.definitions.StructDefinition; + +public interface StructProvider +{ + StructDefinition provide(int structId); +} diff --git a/src/main/java/net/runelite/cache/definitions/providers/TextureProvider.java b/src/main/java/net/runelite/cache/definitions/providers/TextureProvider.java new file mode 100644 index 0000000..f85fec5 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/providers/TextureProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.providers; + +import net.runelite.cache.definitions.TextureDefinition; + +public interface TextureProvider +{ + TextureDefinition[] provide(); +} diff --git a/src/main/java/net/runelite/cache/definitions/providers/UnderlayProvider.java b/src/main/java/net/runelite/cache/definitions/providers/UnderlayProvider.java new file mode 100644 index 0000000..3b0381c --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/providers/UnderlayProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.providers; + +import net.runelite.cache.definitions.UnderlayDefinition; + +public interface UnderlayProvider +{ + UnderlayDefinition provide(int underlayId); +} diff --git a/src/main/java/net/runelite/cache/definitions/savers/InterfaceSaver.java b/src/main/java/net/runelite/cache/definitions/savers/InterfaceSaver.java new file mode 100644 index 0000000..61151a4 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/savers/InterfaceSaver.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.savers; + +import net.runelite.cache.definitions.ClientScript1Instruction; +import net.runelite.cache.definitions.InterfaceDefinition; +import net.runelite.cache.io.OutputStream; + +public class InterfaceSaver +{ + public byte[] save(InterfaceDefinition def) + { + if (def.isIf3) + { + return saveIf3(def); + } + else + { + return saveIf1(def); + } + } + + private byte[] saveIf3(InterfaceDefinition def) + { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + private byte[] saveIf1(InterfaceDefinition def) + { + OutputStream out = new OutputStream(); + out.writeByte(def.type); + out.writeByte(def.menuType); + out.writeShort(def.contentType); + out.writeShort(def.originalX); + out.writeShort(def.originalY); + out.writeShort(def.originalWidth); + out.writeShort(def.originalHeight); + out.writeByte(def.opacity); + out.writeShort(def.parentId); + out.writeShort(def.hoveredSiblingId); + if (def.alternateOperators != null) + { + out.writeByte(def.alternateOperators.length); + for (int i = 0; i < def.alternateOperators.length; ++i) + { + out.writeByte(def.alternateOperators[i]); + out.writeShort(def.alternateRhs[i]); + } + } + else + { + out.writeByte(0); + } + if (def.clientScripts != null) + { + out.writeByte(def.clientScripts.length); + for (int i = 0; i < def.clientScripts.length; ++i) + { + int len = 0; + for (int j = 0; j < def.clientScripts[i].length; ++j) + { + ClientScript1Instruction ins = def.clientScripts[i][j]; + len++; + if (ins.operands != null) + { + len += ins.operands.length; + } + } + out.writeShort(len); + for (int j = 0; j < def.clientScripts[i].length; ++j) + { + ClientScript1Instruction ins = def.clientScripts[i][j]; + out.writeShort(ins.opcode.ordinal()); + if (ins.operands != null) + { + for (int op : ins.operands) + { + out.writeShort(op); + } + } + } + } + } + else + { + out.writeByte(0); + } + if (def.type == 0) + { + out.writeShort(def.scrollHeight); + out.writeByte(def.isHidden ? 1 : 0); + } + if (def.type == 1) + { + out.writeShort(0); + out.writeByte(0); + } + if (def.type == 2) + { + out.writeByte((def.clickMask & 268435456) != 0 ? 1 : 0); + out.writeByte((def.clickMask & 1073741824) != 0 ? 1 : 0); + out.writeByte((def.clickMask & Integer.MIN_VALUE) != 0 ? 1 : 0); + out.writeByte((def.clickMask & 536870912) != 0 ? 1 : 0); + out.writeByte(def.xPitch); + out.writeByte(def.yPitch); + for (int i = 0; i < 20; ++i) + { + if (def.sprites[i] != -1) + { + out.writeByte(1); + out.writeShort(def.xOffsets[i]); + out.writeShort(def.yOffsets[i]); + out.writeShort(def.sprites[i]); + } + else + { + out.writeByte(0); + } + } + for (int i = 0; i < 5; ++i) + { + if (def.configActions[i] != null) + { + out.writeString(def.configActions[i]); + } + else + { + out.writeString(""); + } + } + } + if (def.type == 3) + { + out.writeByte(def.filled ? 1 : 0); + } + if (def.type == 4 || def.type == 1) + { + out.writeByte(def.xTextAlignment); + out.writeByte(def.yTextAlignment); + out.writeByte(def.lineHeight); + out.writeShort(def.fontId); + out.writeByte(def.textShadowed ? 1 : 0); + } + if (def.type == 4) + { + out.writeString(def.text); + out.writeString(def.alternateText); + } + if (def.type == 1 || def.type == 3 || def.type == 4) + { + out.writeInt(def.textColor); + } + if (def.type == 3 || def.type == 4) + { + out.writeInt(def.alternateTextColor); + out.writeInt(def.hoveredTextColor); + out.writeInt(def.alternateHoveredTextColor); + } + if (def.type == 5) + { + out.writeInt(def.spriteId); + out.writeInt(def.alternateSpriteId); + } + if (def.type == 6) + { + out.writeShort(def.modelId); + out.writeShort(def.alternateModelId); + out.writeShort(def.animation); + out.writeShort(def.alternateAnimation); + out.writeShort(def.modelZoom); + out.writeShort(def.rotationX); + out.writeShort(def.rotationZ); + } + if (def.type == 7) + { + out.writeByte(def.xTextAlignment); + out.writeShort(def.fontId); + out.writeByte(def.textShadowed ? 1 : 0); + out.writeInt(def.textColor); + out.writeShort(def.xPitch); + out.writeShort(def.yPitch); + out.writeByte((def.clickMask & 1073741824) != 0 ? 1 : 0); + for (int i = 0; i < 5; ++i) + { + out.writeString(def.configActions[i]); + } + } + if (def.type == 8) + { + out.writeString(def.text); + } + if (def.menuType == 2 || def.type == 2) + { + out.writeString(def.targetVerb); + out.writeString(def.spellName); + out.writeShort((def.clickMask >>> 11) & 63); + } + if (def.menuType == 1 || def.menuType == 4 || def.menuType == 5 || def.menuType == 6) + { + out.writeString(def.tooltip); + } + return out.flip(); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/savers/ItemSaver.java b/src/main/java/net/runelite/cache/definitions/savers/ItemSaver.java new file mode 100644 index 0000000..baa9af3 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/savers/ItemSaver.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.savers; + +import java.util.Map.Entry; +import net.runelite.cache.definitions.ItemDefinition; +import net.runelite.cache.io.OutputStream; + +public class ItemSaver +{ + public byte[] save(ItemDefinition item) + { + OutputStream out = new OutputStream(); + if (item.inventoryModel != 0) + { + out.writeByte(1); + out.writeShort(item.inventoryModel); + } + if (item.name != null) + { + out.writeByte(2); + out.writeString(item.name); + } + out.writeByte(4); + out.writeShort(item.zoom2d); + out.writeByte(5); + out.writeShort(item.xan2d); + out.writeByte(6); + out.writeShort(item.yan2d); + out.writeByte(7); + out.writeShort(item.xOffset2d); + out.writeByte(8); + out.writeShort(item.yOffset2d); + if (item.stackable != 0) + { + out.writeByte(11); + } + out.writeByte(12); + out.writeInt(item.cost); + if (item.members) + { + out.writeByte(16); + } + if (item.maleModel0 != -1 || item.maleOffset != 0) + { + out.writeByte(23); + out.writeShort(item.maleModel0); + out.writeByte(item.maleOffset); + } + if (item.maleModel1 != -1) + { + out.writeByte(24); + out.writeShort(item.maleModel1); + } + if (item.femaleModel0 != -1 || item.femaleOffset != 0) + { + out.writeByte(25); + out.writeShort(item.femaleModel0); + out.writeByte(item.femaleOffset); + } + if (item.femaleModel1 != -1) + { + out.writeByte(26); + out.writeShort(item.femaleModel1); + } + for (int i = 0; i < 5; ++i) + { + if (item.options[i] != null) + { + out.writeByte(30 + i); + out.writeString(item.options[i]); + } + } + for (int i = 0; i < 5; ++i) + { + if (item.interfaceOptions[i] != null) + { + out.writeByte(35 + i); + out.writeString(item.interfaceOptions[i]); + } + } + if (item.colorFind != null && item.colorReplace != null) + { + out.writeByte(40); + out.writeByte(item.colorFind.length); + for (int i = 0; i < item.colorFind.length; ++i) + { + out.writeShort(item.colorFind[i]); + out.writeShort(item.colorReplace[i]); + } + } + if (item.textureFind != null && item.textureReplace != null) + { + out.writeByte(41); + out.writeByte(item.textureFind.length); + for (int i = 0; i < item.textureFind.length; ++i) + { + out.writeShort(item.textureFind[i]); + out.writeShort(item.textureReplace[i]); + } + } + out.writeByte(42); + out.writeByte(item.shiftClickDropIndex); + if (item.isTradeable) + { + out.writeByte(65); + } + if (item.maleModel2 != -1) + { + out.writeByte(78); + out.writeShort(item.maleModel2); + } + if (item.femaleModel2 != -1) + { + out.writeByte(79); + out.writeShort(item.femaleModel2); + } + if (item.maleHeadModel != -1) + { + out.writeByte(90); + out.writeShort(item.maleHeadModel); + } + if (item.femaleHeadModel != -1) + { + out.writeByte(91); + out.writeShort(item.femaleHeadModel); + } + if (item.maleHeadModel2 != -1) + { + out.writeByte(92); + out.writeShort(item.maleHeadModel2); + } + if (item.femaleHeadModel2 != -1) + { + out.writeByte(93); + out.writeShort(item.femaleHeadModel2); + } + out.writeByte(95); + out.writeShort(item.zan2d); + if (item.notedID != -1) + { + out.writeByte(97); + out.writeShort(item.notedID); + } + if (item.notedTemplate != -1) + { + out.writeByte(98); + out.writeShort(item.notedTemplate); + } + if (item.countObj != null) + { + for (int i = 0; i < 10; ++i) + { + out.writeByte(100 + i); + out.writeShort(item.countObj[i]); + out.writeShort(item.countCo[i]); + } + } + out.writeByte(110); + out.writeShort(item.resizeX); + out.writeByte(111); + out.writeShort(item.resizeY); + out.writeByte(112); + out.writeShort(item.resizeZ); + out.writeByte(113); + out.writeByte(item.ambient); + out.writeByte(114); + out.writeByte(item.contrast); + out.writeByte(115); + out.writeByte(item.team); + if (item.boughtId != -1) + { + out.writeByte(139); + out.writeShort(item.boughtId); + } + if (item.boughtTemplateId != -1) + { + out.writeByte(140); + out.writeShort(item.boughtTemplateId); + } + if (item.placeholderId != -1) + { + out.writeByte(148); + out.writeShort(item.placeholderId); + } + if (item.placeholderTemplateId != -1) + { + out.writeByte(149); + out.writeShort(item.placeholderTemplateId); + } + if (item.params != null) + { + out.writeByte(249); + out.writeByte(item.params.size()); + for (Entry entry : item.params.entrySet()) + { + out.writeByte(entry.getValue() instanceof String ? 1 : 0); + out.write24BitInt(entry.getKey()); + if (entry.getValue() instanceof String) + { + out.writeString((String) entry.getValue()); + } + else + { + out.writeInt((Integer) entry.getValue()); + } + } + } + out.writeByte(0); + + return out.flip(); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/savers/LocationSaver.java b/src/main/java/net/runelite/cache/definitions/savers/LocationSaver.java new file mode 100644 index 0000000..2086bd7 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/savers/LocationSaver.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.savers; + +import com.google.common.collect.LinkedListMultimap; +import com.google.common.collect.Multimap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import net.runelite.cache.definitions.LocationsDefinition; +import net.runelite.cache.io.OutputStream; +import net.runelite.cache.region.Location; + +public class LocationSaver +{ + public byte[] save(LocationsDefinition locs) + { + Multimap locById = LinkedListMultimap.create(); + List sortedLocs = new ArrayList<>(locs.getLocations()); + sortedLocs.sort((l1, l2) -> Integer.compare(l1.getId(), l2.getId())); + for (Location loc : sortedLocs) + { + locById.put(loc.getId(), loc); + } + OutputStream out = new OutputStream(); + int prevId = -1; + for (Integer id : locById.keySet()) + { + int diffId = id - prevId; + prevId = id; + + out.writeShortSmart(diffId); + + Collection locations = locById.get(id); + int position = 0; + for (Location loc : locations) + { + int packedPosition = (loc.getPosition().getZ() << 12) + | (loc.getPosition().getX() << 6) + | (loc.getPosition().getY()); + + int diffPos = packedPosition - position; + position = packedPosition; + + out.writeShortSmart(diffPos + 1); + + int packedAttributes = (loc.getType() << 2) | loc.getOrientation(); + out.writeByte(packedAttributes); + } + + out.writeShortSmart(0); + } + out.writeShortSmart(0); + return out.flip(); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/savers/MapSaver.java b/src/main/java/net/runelite/cache/definitions/savers/MapSaver.java new file mode 100644 index 0000000..855ccd4 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/savers/MapSaver.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.savers; + +import net.runelite.cache.definitions.MapDefinition; +import net.runelite.cache.definitions.MapDefinition.Tile; +import net.runelite.cache.io.OutputStream; +import static net.runelite.cache.region.Region.X; +import static net.runelite.cache.region.Region.Y; +import static net.runelite.cache.region.Region.Z; + +public class MapSaver +{ + public byte[] save(MapDefinition map) + { + Tile[][][] tiles = map.getTiles(); + OutputStream out = new OutputStream(); + for (int z = 0; z < Z; z++) + { + for (int x = 0; x < X; x++) + { + for (int y = 0; y < Y; y++) + { + Tile tile = tiles[z][x][y]; + if (tile.attrOpcode != 0) + { + out.writeByte(tile.attrOpcode); + out.writeByte(tile.overlayId); + } + if (tile.settings != 0) + { + out.writeByte(tile.settings + 49); + } + if (tile.underlayId != 0) + { + out.writeByte(tile.underlayId + 81); + } + if (tile.height == null) + { + out.writeByte(0); + } + else + { + out.writeByte(1); + out.writeByte(tile.height); + } + } + } + } + return out.flip(); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/savers/NpcSaver.java b/src/main/java/net/runelite/cache/definitions/savers/NpcSaver.java new file mode 100644 index 0000000..577681c --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/savers/NpcSaver.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.savers; + +import java.util.Map; +import net.runelite.cache.definitions.NpcDefinition; +import net.runelite.cache.io.OutputStream; + +public class NpcSaver +{ + public byte[] save(NpcDefinition npc) + { + OutputStream out = new OutputStream(); + if (npc.models != null) + { + out.writeByte(1); + out.writeByte(npc.models.length); + for (int modelId : npc.models) + { + out.writeShort(modelId); + } + } + if (npc.name != null) + { + out.writeByte(2); + out.writeString(npc.name); + } + if (npc.size != 1) + { + out.writeByte(12); + out.writeByte(npc.size); + } + if (npc.standingAnimation != -1) + { + out.writeByte(13); + out.writeShort(npc.standingAnimation); + } + if (npc.walkingAnimation != -1) + { + out.writeByte(14); + out.writeShort(npc.walkingAnimation); + } + if (npc.rotateLeftAnimation != -1) + { + out.writeByte(15); + out.writeShort(npc.rotateLeftAnimation); + } + if (npc.rotateRightAnimation != -1) + { + out.writeByte(16); + out.writeShort(npc.rotateRightAnimation); + } + if (npc.rotate180Animation != -1 || npc.rotate90LeftAnimation != -1 || npc.rotate90RightAnimation != -1) + { + out.writeByte(17); + out.writeShort(npc.walkingAnimation); + out.writeShort(npc.rotate180Animation); + out.writeShort(npc.rotate90RightAnimation); + out.writeShort(npc.rotate90LeftAnimation); + } + for (int i = 0; i < 5; ++i) + { + if (npc.actions[i] != null) + { + out.writeByte(30 + i); + out.writeString(npc.actions[i]); + } + } + if (npc.recolorToFind != null && npc.recolorToReplace != null) + { + out.writeByte(40); + out.writeByte(npc.recolorToFind.length); + for (int i = 0; i < npc.recolorToFind.length; ++i) + { + out.writeShort(npc.recolorToFind[i]); + out.writeShort(npc.recolorToReplace[i]); + } + } + if (npc.retextureToFind != null && npc.retextureToReplace != null) + { + out.writeByte(41); + out.writeByte(npc.retextureToFind.length); + for (int i = 0; i < npc.retextureToFind.length; ++i) + { + out.writeShort(npc.retextureToFind[i]); + out.writeShort(npc.retextureToReplace[i]); + } + } + if (npc.chatheadModels != null) + { + out.writeByte(60); + out.writeByte(npc.chatheadModels.length); + for (int modelId : npc.chatheadModels) + { + out.writeShort(modelId); + } + } + if (!npc.isMinimapVisible) + { + out.writeByte(93); + } + if (npc.combatLevel != -1) + { + out.writeByte(95); + out.writeShort(npc.combatLevel); + } + out.writeByte(97); + out.writeShort(npc.widthScale); + out.writeByte(98); + out.writeShort(npc.heightScale); + if (npc.hasRenderPriority) + { + out.writeByte(99); + } + out.writeByte(100); + out.writeByte(npc.ambient); + out.writeByte(101); + out.writeByte(npc.contrast); + if (npc.headIcon != -1) + { + out.writeByte(102); + out.writeShort(npc.headIcon); + } + out.writeByte(103); + out.writeShort(npc.rotationSpeed); + if (!npc.isInteractable) + { + out.writeByte(107); + } + if (!npc.rotationFlag) + { + out.writeByte(109); + } + if (npc.isPet) + { + out.writeByte(111); + } + if (npc.configs != null) + { + out.writeByte(118); + out.writeShort(npc.varbitId); + out.writeShort(npc.varpIndex); + + int[] c = npc.configs; + out.writeShort(c[c.length - 1]); + out.writeByte(c.length - 2); + for (int i = 0; i <= c.length - 2; ++i) + { + out.writeShort(c[i]); + } + } + if (npc.params != null) + { + out.writeByte(249); + out.writeByte(npc.params.size()); + for (Map.Entry entry : npc.params.entrySet()) + { + out.writeByte(entry.getValue() instanceof String ? 1 : 0); + out.write24BitInt(entry.getKey()); + if (entry.getValue() instanceof String) + { + out.writeString((String) entry.getValue()); + } + else + { + out.writeInt((Integer) entry.getValue()); + } + } + } + out.writeByte(0); + return out.flip(); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/savers/ObjectSaver.java b/src/main/java/net/runelite/cache/definitions/savers/ObjectSaver.java new file mode 100644 index 0000000..8412240 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/savers/ObjectSaver.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.savers; + +import java.util.Map; +import net.runelite.cache.definitions.ObjectDefinition; +import net.runelite.cache.io.OutputStream; + +public class ObjectSaver +{ + public byte[] save(ObjectDefinition obj) + { + OutputStream out = new OutputStream(); + if (obj.getObjectTypes() != null && obj.getObjectModels() != null) + { + out.writeByte(1); + out.writeByte(obj.getObjectTypes().length); + for (int i = 0; i < obj.getObjectTypes().length; ++i) + { + out.writeShort(obj.getObjectModels()[i]); + out.writeByte(obj.getObjectTypes()[i]); + } + } + if (obj.getName() != null) + { + out.writeByte(2); + out.writeString(obj.getName()); + } + if (obj.getObjectTypes() == null && obj.getObjectModels() != null) + { + out.writeByte(5); + out.writeByte(obj.getObjectModels().length); + for (int i = 0; i < obj.getObjectModels().length; ++i) + { + out.writeShort(obj.getObjectModels()[i]); + } + } + out.writeByte(14); + out.writeByte(obj.getSizeX()); + out.writeByte(15); + out.writeByte(obj.getSizeY()); + if (obj.getInteractType() == 0 && !obj.isBlocksProjectile()) + { + out.writeByte(17); + } + else if (!obj.isBlocksProjectile()) + { + out.writeByte(18); + } + if (obj.getWallOrDoor() != -1) + { + out.writeByte(19); + out.writeByte(obj.getWallOrDoor()); + } + if (obj.getContouredGround() == 0) + { + out.writeByte(21); + } + if (!obj.isMergeNormals()) + { + out.writeByte(22); + } + if (obj.isABool2111()) + { + out.writeByte(23); + } + if (obj.getAnimationID() != -1) + { + out.writeByte(24); + out.writeShort(obj.getAnimationID()); + } + if (obj.getInteractType() == 1) + { + out.writeByte(27); + } + out.writeByte(28); + out.writeByte(obj.getDecorDisplacement()); + out.writeByte(29); + out.writeByte(obj.getAmbient()); + out.writeByte(39); + out.writeByte(obj.getContrast() / 25); + for (int i = 0; i < 5; ++i) + { + out.writeByte(30 + i); + String action = obj.getActions()[i]; + out.writeString(action != null ? action : "Hidden"); + } + if (obj.getRecolorToFind() != null && obj.getRecolorToReplace() != null) + { + out.writeByte(40); + out.writeByte(obj.getRecolorToFind().length); + for (int i = 0; i < obj.getRecolorToFind().length; ++i) + { + out.writeShort(obj.getRecolorToFind()[i]); + out.writeShort(obj.getRecolorToReplace()[i]); + } + } + if (obj.getRetextureToFind() != null && obj.getTextureToReplace() != null) + { + out.writeByte(41); + out.writeByte(obj.getRetextureToFind().length); + for (int i = 0; i < obj.getRetextureToFind().length; ++i) + { + out.writeShort(obj.getRetextureToFind()[i]); + out.writeShort(obj.getTextureToReplace()[i]); + } + } + if (obj.isRotated()) + { + out.writeByte(62); + } + if (!obj.isShadow()) + { + out.writeByte(64); + } + out.writeByte(65); + out.writeShort(obj.getModelSizeX()); + out.writeByte(66); + out.writeShort(obj.getModelSizeHeight()); + out.writeByte(67); + out.writeShort(obj.getModelSizeY()); + if (obj.getMapSceneID() != -1) + { + out.writeByte(68); + out.writeShort(obj.getMapSceneID()); + } + out.writeByte(70); + out.writeShort(obj.getOffsetX()); + out.writeByte(71); + out.writeShort(obj.getOffsetHeight()); + out.writeByte(72); + out.writeShort(obj.getOffsetY()); + if (obj.isObstructsGround()) + { + out.writeByte(73); + } + if (obj.isHollow()) + { + out.writeByte(74); + } + if (obj.getSupportsItems() != -1) + { + out.writeByte(75); + out.writeByte(obj.getSupportsItems()); + } + if (obj.getAmbientSoundId() != -1) + { + out.writeByte(78); + out.writeShort(obj.getAmbientSoundId()); + out.writeByte(obj.getAnInt2083()); + } + if (obj.getAnIntArray2084() != null) + { + out.writeByte(79); + out.writeShort(obj.getAnInt2112()); + out.writeShort(obj.getAnInt2113()); + out.writeByte(obj.getAnInt2083()); + out.writeByte(obj.getAnIntArray2084().length); + for (int i : obj.getAnIntArray2084()) + { + out.writeShort(i); + } + } + if (obj.getContouredGround() != -1) + { + out.writeByte(81); + out.writeByte(obj.getContouredGround() / 256); + } + if (obj.getMapAreaId() != -1) + { + out.writeByte(82); + out.writeShort(obj.getMapAreaId()); + } + if (obj.getConfigChangeDest() != null) + { + out.writeByte(92); + out.writeShort(obj.getVarbitID()); + out.writeShort(obj.getVarpID()); + + int[] c = obj.getConfigChangeDest(); + out.writeShort(c[c.length - 1]); + out.writeByte(c.length - 2); + for (int i = 0; i <= c.length - 2; ++i) + { + out.writeShort(c[i]); + } + } + if (obj.getParams() != null) + { + out.writeByte(249); + out.writeByte(obj.getParams().size()); + for (Map.Entry entry : obj.getParams().entrySet()) + { + out.writeByte(entry.getValue() instanceof String ? 1 : 0); + out.write24BitInt(entry.getKey()); + if (entry.getValue() instanceof String) + { + out.writeString((String) entry.getValue()); + } + else + { + out.writeInt((Integer) entry.getValue()); + } + } + } + out.writeByte(0); + return out.flip(); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/savers/ScriptSaver.java b/src/main/java/net/runelite/cache/definitions/savers/ScriptSaver.java new file mode 100644 index 0000000..3b130c4 --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/savers/ScriptSaver.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.savers; + +import java.util.Map; +import java.util.Map.Entry; +import net.runelite.cache.definitions.ScriptDefinition; +import net.runelite.cache.io.OutputStream; +import static net.runelite.cache.script.Opcodes.SCONST; +import static net.runelite.cache.script.Opcodes.POP_INT; +import static net.runelite.cache.script.Opcodes.POP_STRING; +import static net.runelite.cache.script.Opcodes.RETURN; + +public class ScriptSaver +{ + public byte[] save(ScriptDefinition script) + { + int[] instructions = script.getInstructions(); + int[] intOperands = script.getIntOperands(); + String[] stringOperands = script.getStringOperands(); + Map[] switches = script.getSwitches(); + + OutputStream out = new OutputStream(); + out.writeByte(0); // null string + for (int i = 0; i < instructions.length; ++i) + { + int opcode = instructions[i]; + out.writeShort(opcode); + if (opcode == SCONST) + { + out.writeString(stringOperands[i]); + } + else if (opcode < 100 && opcode != RETURN && opcode != POP_INT && opcode != POP_STRING) + { + out.writeInt(intOperands[i]); + } + else + { + out.writeByte(intOperands[i]); + } + } + out.writeInt(instructions.length); + out.writeShort(script.getLocalIntCount()); + out.writeShort(script.getLocalStringCount()); + out.writeShort(script.getIntStackCount()); + out.writeShort(script.getStringStackCount()); + int switchStart = out.getOffset(); + if (switches == null) + { + out.writeByte(0); + } + else + { + out.writeByte(switches.length); + for (Map s : switches) + { + out.writeShort(s.size()); + for (Entry e : s.entrySet()) + { + out.writeInt(e.getKey()); + out.writeInt(e.getValue()); + } + } + } + int switchLength = out.getOffset() - switchStart; + out.writeShort(switchLength); + return out.flip(); + } +} diff --git a/src/main/java/net/runelite/cache/definitions/sound/AudioEnvelopeDefinition.java b/src/main/java/net/runelite/cache/definitions/sound/AudioEnvelopeDefinition.java new file mode 100644 index 0000000..46d709f --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/sound/AudioEnvelopeDefinition.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.sound; + +public class AudioEnvelopeDefinition +{ + public int segments = 2; + public int[] durations = new int[2]; + public int[] phases = new int[2]; + public int start; + public int end; + public int form; + public int ticks; + public int phaseIndex; + public int step; + public int amplitude; + public int max; + + public AudioEnvelopeDefinition() + { + this.durations[0] = 0; + this.durations[1] = '\uffff'; + this.phases[0] = 0; + this.phases[1] = '\uffff'; + } + + public final int step(int var1) + { + if (this.max >= this.ticks) + { + this.amplitude = this.phases[this.phaseIndex++] << 15; + + if (this.phaseIndex >= this.segments) + { + this.phaseIndex = this.segments - 1; + } + + this.ticks = (int) ((double) this.durations[this.phaseIndex] / 65536.0 * (double) var1); + + if (this.ticks > this.max) + { + this.step = ((this.phases[this.phaseIndex] << 15) - this.amplitude) / (this.ticks - this.max); + } + } + this.amplitude += this.step; + ++this.max; + + return this.amplitude - this.step >> 15; + } + + public final void reset() + { + this.ticks = 0; + this.phaseIndex = 0; + this.step = 0; + this.amplitude = 0; + this.max = 0; + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/definitions/sound/InstrumentDefinition.java b/src/main/java/net/runelite/cache/definitions/sound/InstrumentDefinition.java new file mode 100644 index 0000000..fafaa7b --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/sound/InstrumentDefinition.java @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.sound; + +import java.util.Random; + +public class InstrumentDefinition +{ + public AudioEnvelopeDefinition volume; + public AudioEnvelopeDefinition pitchModifier; + public AudioEnvelopeDefinition field1175; + public AudioEnvelopeDefinition release; + public AudioEnvelopeDefinition volumeMultiplier; + public AudioEnvelopeDefinition volumeMultiplierAmplitude; + public AudioEnvelopeDefinition pitchModifierAmplitude; + public AudioEnvelopeDefinition pitch; + + public int[] oscillatorDelays = new int[] + { + 0, 0, 0, 0, 0 + }; + public int[] oscillatorPitch = new int[] + { + 0, 0, 0, 0, 0 + }; + public int[] oscillatorVolume = new int[] + { + 0, 0, 0, 0, 0 + }; + + public SoundEffectDefinition filter; + public AudioEnvelopeDefinition filterEnvelope; + + static int[] samples = new int[220500]; + + static int[] NOISE = new int[32768]; + static int[] AUDIO_SINE = new int[32768]; + + static int[] phases = new int[5]; + static int[] delays = new int[5]; + + static int[] volumeSteps = new int[5]; + static int[] pitchSteps = new int[5]; + static int[] pitchBaseSteps = new int[5]; + + public int duration = 500; + public int delayDecay = 100; + public int delayTime = 0; + public int offset = 0; + + static + { + Random random = new Random(0); + + for (int i = 0; i < 32768; ++i) + { + InstrumentDefinition.NOISE[i] = (random.nextInt() & 2) - 1; + InstrumentDefinition.AUDIO_SINE[i] = (int) (Math.sin((double) i / 5215.1903) * 16384.0); + } + } + + public final int[] synthesize(int var1, int var2) + { + int var16; + int var15; + int var14; + int var11; + int var12; + int var13; + + InstrumentDefinition.method3854(samples, 0, var1); + + if (var2 < 10) + { + return samples; + } + + double var3 = (double) var1 / ((double) var2 + 0.0); + + this.pitch.reset(); + this.volume.reset(); + + int var5 = 0; + int var6 = 0; + int var7 = 0; + + if (this.pitchModifier != null) + { + this.pitchModifier.reset(); + this.pitchModifierAmplitude.reset(); + + var5 = (int) ((double) (this.pitchModifier.end - this.pitchModifier.start) * 32.768 / var3); + var6 = (int) ((double) this.pitchModifier.start * 32.768 / var3); + } + + int var8 = 0; + int var9 = 0; + int var10 = 0; + + if (this.volumeMultiplier != null) + { + this.volumeMultiplier.reset(); + this.volumeMultiplierAmplitude.reset(); + + var8 = (int) ((double) (this.volumeMultiplier.end - this.volumeMultiplier.start) * 32.768 / var3); + var9 = (int) ((double) this.volumeMultiplier.start * 32.768 / var3); + } + + for (var11 = 0; var11 < 5; ++var11) + { + if (this.oscillatorVolume[var11] == 0) + { + continue; + } + + InstrumentDefinition.phases[var11] = 0; + InstrumentDefinition.delays[var11] = (int) ((double) this.oscillatorDelays[var11] * var3); + InstrumentDefinition.volumeSteps[var11] = (this.oscillatorVolume[var11] << 14) / 100; + InstrumentDefinition.pitchSteps[var11] = (int) ((double) (this.pitch.end - this.pitch.start) * 32.768 * Math.pow(1.0057929410678534, this.oscillatorPitch[var11]) / var3); + InstrumentDefinition.pitchBaseSteps[var11] = (int) ((double) this.pitch.start * 32.768 / var3); + } + + for (var11 = 0; var11 < var1; ++var11) + { + var12 = this.pitch.step(var1); + var13 = this.volume.step(var1); + + if (this.pitchModifier != null) + { + var14 = this.pitchModifier.step(var1); + var15 = this.pitchModifierAmplitude.step(var1); + var12 += this.evaluateWave(var7, var15, this.pitchModifier.form) >> 1; + var7 = var7 + var6 + (var14 * var5 >> 16); + } + + if (this.volumeMultiplier != null) + { + var14 = this.volumeMultiplier.step(var1); + var15 = this.volumeMultiplierAmplitude.step(var1); + var13 = var13 * ((this.evaluateWave(var10, var15, this.volumeMultiplier.form) >> 1) + 32768) >> 15; + var10 = var10 + var9 + (var14 * var8 >> 16); + } + + for (var14 = 0; var14 < 5; ++var14) + { + if (this.oscillatorVolume[var14] == 0 || (var15 = delays[var14] + var11) >= var1) + { + continue; + } + + int[] arrn = samples; + int n = var15; + arrn[n] = arrn[n] + this.evaluateWave(phases[var14], var13 * volumeSteps[var14] >> 15, this.pitch.form); + int[] arrn2 = phases; + int n2 = var14; + arrn2[n2] = arrn2[n2] + ((var12 * pitchSteps[var14] >> 16) + pitchBaseSteps[var14]); + } + } + + if (this.release != null) + { + this.release.reset(); + this.field1175.reset(); + + var11 = 0; + boolean var20 = true; + + for (var14 = 0; var14 < var1; ++var14) + { + var15 = this.release.step(var1); + var16 = this.field1175.step(var1); + var12 = var20 ? (var15 * (this.release.end - this.release.start) >> 8) + this.release.start : (var16 * (this.release.end - this.release.start) >> 8) + this.release.start; + if ((var11 += 256) >= var12) + { + var11 = 0; + } + if (!var20) + { + continue; + } + InstrumentDefinition.samples[var14] = 0; + } + } + if (this.delayTime > 0 && this.delayDecay > 0) + { + for (var12 = var11 = (int) ((double) this.delayTime * var3); var12 < var1; ++var12) + { + int[] arrn = samples; + int n = var12; + + arrn[n] = arrn[n] + samples[var12 - var11] * this.delayDecay / 100; + } + } + if (this.filter.pairs[0] > 0 || this.filter.pairs[1] > 0) + { + this.filterEnvelope.reset(); + + var11 = this.filterEnvelope.step(var1 + 1); + var12 = this.filter.compute(0, (float) var11 / 65536.0f); + var13 = this.filter.compute(1, (float) var11 / 65536.0f); + + if (var1 >= var12 + var13) + { + int var17; + + var14 = 0; + var15 = var13; + + if (var13 > var1 - var12) + { + var15 = var1 - var12; + } + + while (var14 < var15) + { + var16 = (int) ((long) samples[var14 + var12] * (long) SoundEffectDefinition.fowardMultiplier >> 16); + + for (var17 = 0; var17 < var12; ++var17) + { + var16 += (int) ((long) samples[var14 + var12 - 1 - var17] * (long) SoundEffectDefinition.coefficients[0][var17] >> 16); + } + + for (var17 = 0; var17 < var14; ++var17) + { + var16 -= (int) ((long) samples[var14 - 1 - var17] * (long) SoundEffectDefinition.coefficients[1][var17] >> 16); + } + + InstrumentDefinition.samples[var14] = var16; + var11 = this.filterEnvelope.step(var1 + 1); + ++var14; + } + var15 = 128; + + do + { + int var18; + + if (var15 > var1 - var12) + { + var15 = var1 - var12; + } + + while (var14 < var15) + { + var17 = (int) ((long) samples[var14 + var12] * (long) SoundEffectDefinition.fowardMultiplier >> 16); + + for (var18 = 0; var18 < var12; ++var18) + { + var17 += (int) ((long) samples[var14 + var12 - 1 - var18] * (long) SoundEffectDefinition.coefficients[0][var18] >> 16); + } + + for (var18 = 0; var18 < var13; ++var18) + { + var17 -= (int) ((long) samples[var14 - 1 - var18] * (long) SoundEffectDefinition.coefficients[1][var18] >> 16); + } + + InstrumentDefinition.samples[var14] = var17; + var11 = this.filterEnvelope.step(var1 + 1); + ++var14; + } + if (var14 >= var1 - var12) + { + while (var14 < var1) + { + var17 = 0; + for (var18 = var14 + var12 - var1; var18 < var12; ++var18) + { + var17 += (int) ((long) samples[var14 + var12 - 1 - var18] + * (long) SoundEffectDefinition.coefficients[0][var18] >> 16); + } + for (var18 = 0; var18 < var13; ++var18) + { + var17 -= (int) ((long) samples[var14 - 1 - var18] + * (long) SoundEffectDefinition.coefficients[1][var18] >> 16); + } + InstrumentDefinition.samples[var14] = var17; + this.filterEnvelope.step(var1 + 1); + ++var14; + } + break; + } + var12 = this.filter.compute(0, (float) var11 / 65536.0f); + var13 = this.filter.compute(1, (float) var11 / 65536.0f); + var15 += 128; + } + while (true); + } + } + for (var11 = 0; var11 < var1; ++var11) + { + if (samples[var11] < -32768) + { + InstrumentDefinition.samples[var11] = -32768; + } + + if (samples[var11] <= 32767) + { + continue; + } + + InstrumentDefinition.samples[var11] = 32767; + } + + return samples; + } + + private static void method3854(int[] var1, int var2, int var3) + { + var3 = var3 + var2 - 7; + + while (var2 < var3) + { + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + } + + while (var2 < (var3 += 7)) + { + var1[var2++] = 0; + } + } + + public final int evaluateWave(int var1, int var2, int var3) + { + return var3 == 1 ? ((var1 & 32767) < 16384 ? var2 : -var2) : (var3 == 2 ? AUDIO_SINE[var1 & 32767] * var2 >> 14 : (var3 == 3 ? (var2 * (var1 & 32767) >> 14) - var2 : (var3 == 4 ? var2 * NOISE[var1 / 2607 & 32767] : 0))); + } +} + diff --git a/src/main/java/net/runelite/cache/definitions/sound/SoundEffectDefinition.java b/src/main/java/net/runelite/cache/definitions/sound/SoundEffectDefinition.java new file mode 100644 index 0000000..7f6d71d --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/sound/SoundEffectDefinition.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.sound; + +public class SoundEffectDefinition +{ + public int[][][] phases = new int[2][2][4]; + public int[] pairs = new int[2]; + public int[] unity = new int[2]; + public int[][][] magnitudes = new int[2][2][4]; + + public static float[][] minCoefficients = new float[2][8]; + public static int[][] coefficients = new int[2][8]; + public static float fowardMinCoefficientMultiplier; + public static int fowardMultiplier; + + public int compute(int var1, float var2) + { + float var3; + int var4; + + if (var1 == 0) + { + var3 = (float) this.unity[0] + (float) (this.unity[1] - this.unity[0]) * var2; + + fowardMinCoefficientMultiplier = (float) Math.pow(0.1, (var3 *= 0.0030517578f) / 20.0f); + fowardMultiplier = (int) (fowardMinCoefficientMultiplier * 65536.0f); + } + + if (this.pairs[var1] == 0) + { + return 0; + } + + var3 = this.interpolateMagniture(var1, 0, var2); + + minCoefficients[var1][0] = -2.0f * var3 * (float) Math.cos(this.interpolatePhase(var1, 0, var2)); + minCoefficients[var1][1] = var3 * var3; + + for (var4 = 1; var4 < this.pairs[var1]; ++var4) + { + var3 = this.interpolateMagniture(var1, var4, var2); + + float var5 = -2.0f * var3 * (float) Math.cos(this.interpolatePhase(var1, var4, var2)); + float var6 = var3 * var3; + + minCoefficients[var1][var4 * 2 + 1] = minCoefficients[var1][var4 * 2 - 1] * var6; + minCoefficients[var1][var4 * 2] = minCoefficients[var1][var4 * 2 - 1] * var5 + minCoefficients[var1][var4 * 2 - 2] * var6; + + for (int var7 = var4 * 2 - 1; var7 >= 2; --var7) + { + float[] arrf = minCoefficients[var1]; + int n = var7; + + arrf[n] = arrf[n] + (minCoefficients[var1][var7 - 1] * var5 + minCoefficients[var1][var7 - 2] * var6); + } + + float[] arrf = minCoefficients[var1]; + arrf[1] = arrf[1] + (minCoefficients[var1][0] * var5 + var6); + + float[] arrf2 = minCoefficients[var1]; + arrf2[0] = arrf2[0] + var5; + } + + if (var1 == 0) + { + var4 = 0; + while (var4 < this.pairs[0] * 2) + { + float[] arrf = minCoefficients[0]; + int n = var4++; + + arrf[n] = arrf[n] * fowardMinCoefficientMultiplier; + } + } + + for (var4 = 0; var4 < this.pairs[var1] * 2; ++var4) + { + coefficients[var1][var4] = (int) (minCoefficients[var1][var4] * 65536.0f); + } + + return this.pairs[var1] * 2; + } + + public float interpolateMagniture(int var1, int var2, float var3) + { + float var4 = (float) this.magnitudes[var1][0][var2] + var3 * (float) (this.magnitudes[var1][1][var2] - this.magnitudes[var1][0][var2]); + + return 1.0f - (float) Math.pow(10.0, (-(var4 *= 0.0015258789f)) / 20.0f); + } + + public float interpolatePhase(int var1, int var2, float var3) + { + float var4 = (float) this.phases[var1][0][var2] + var3 * (float) (this.phases[var1][1][var2] - this.phases[var1][0][var2]); + + return normalise(var4 *= 1.2207031E-4f); + } + + public static float normalise(float var1) + { + float var2 = 32.703197f * (float) Math.pow(2.0, var1); + + return var2 * 3.1415927f / 11025.0f; + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/definitions/sound/SoundEffectTrackDefinition.java b/src/main/java/net/runelite/cache/definitions/sound/SoundEffectTrackDefinition.java new file mode 100644 index 0000000..6cbbbcc --- /dev/null +++ b/src/main/java/net/runelite/cache/definitions/sound/SoundEffectTrackDefinition.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.sound; + +public class SoundEffectTrackDefinition +{ + public int start; + public InstrumentDefinition[] instruments = new InstrumentDefinition[10]; + public int end; + + public final byte[] mix() + { + int var2; + int var1 = 0; + + for (var2 = 0; var2 < 10; ++var2) + { + if (this.instruments[var2] == null || this.instruments[var2].duration + this.instruments[var2].offset <= var1) + { + continue; + } + + var1 = this.instruments[var2].duration + this.instruments[var2].offset; + } + + if (var1 == 0) + { + return new byte[0]; + } + + var2 = var1 * 22050 / 1000; + + byte[] var3 = new byte[var2]; + + for (int i = 0; i < 10; ++i) + { + if (this.instruments[i] == null) + { + continue; + } + + int var5 = this.instruments[i].duration * 22050 / 1000; + int var6 = this.instruments[i].offset * 22050 / 1000; + + int[] var7 = this.instruments[i].synthesize(var5, this.instruments[i].duration); + + for (int j = 0; j < var5; ++j) + { + int var9 = (var7[j] >> 8) + var3[j + var6]; + + if ((var9 + 128 & -256) != 0) + { + var9 = var9 >> 31 ^ 127; + } + + var3[j + var6] = (byte) var9; + } + } + + return var3; + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/fs/Archive.java b/src/main/java/net/runelite/cache/fs/Archive.java new file mode 100644 index 0000000..d7b8435 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/Archive.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.fs; + +import java.io.IOException; +import net.runelite.cache.index.FileData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Archive +{ + private static final Logger logger = LoggerFactory.getLogger(Archive.class); + + private final Index index; // member of this index + + private final int archiveId; + private int nameHash; + private int crc; + private int revision; + private int compression; + private FileData[] fileData; + private byte[] hash; // used by webservice, sha256 hash of content + + public Archive(Index index, int id) + { + this.index = index; + this.archiveId = id; + } + + @Override + public int hashCode() + { + int hash = 7; + hash = 47 * hash + this.archiveId; + hash = 47 * hash + this.nameHash; + hash = 47 * hash + this.revision; + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final Archive other = (Archive) obj; + if (this.archiveId != other.archiveId) + { + return false; + } + if (this.nameHash != other.nameHash) + { + return false; + } + if (this.revision != other.revision) + { + return false; + } + return true; + } + + public Index getIndex() + { + return index; + } + + public byte[] decompress(byte[] data) throws IOException + { + return decompress(data, null); + } + + public byte[] decompress(byte[] data, int[] keys) throws IOException + { + if (data == null) + { + return null; + } + + byte[] encryptedData = data; + + Container container = Container.decompress(encryptedData, keys); + if (container == null) + { + logger.warn("Unable to decrypt archive {}", this); + return null; + } + + byte[] decompressedData = container.data; + + if (this.crc != container.crc) + { + logger.warn("crc mismatch for archive {}/{}", index.getId(), this.getArchiveId()); + throw new IOException("CRC mismatch for " + index.getId() + "/" + this.getArchiveId()); + } + + if (container.revision != -1 && this.getRevision() != container.revision) + { + // compressed data doesn't always include a revision, but check it if it does + logger.warn("revision mismatch for archive {}/{}, expected {} was {}", + index.getId(), this.getArchiveId(), + this.getRevision(), container.revision); + // I've seen this happen with vanilla caches where the + // revision in the index data differs from the revision + // stored for the archive data on disk... I assume this + // is more correct + this.setRevision(container.revision); + } + + setCompression(container.compression); + return decompressedData; + } + + public ArchiveFiles getFiles(byte[] data) throws IOException + { + return getFiles(data, null); + } + + public ArchiveFiles getFiles(byte[] data, int[] keys) throws IOException + { + byte[] decompressedData = decompress(data, keys); + + ArchiveFiles files = new ArchiveFiles(); + for (FileData fileEntry : fileData) + { + FSFile file = new FSFile(fileEntry.getId()); + file.setNameHash(fileEntry.getNameHash()); + files.addFile(file); + } + files.loadContents(decompressedData); + return files; + } + + public int getArchiveId() + { + return archiveId; + } + + public int getNameHash() + { + return nameHash; + } + + public void setNameHash(int nameHash) + { + this.nameHash = nameHash; + } + + public int getCrc() + { + return crc; + } + + public void setCrc(int crc) + { + this.crc = crc; + } + + public int getRevision() + { + return revision; + } + + public void setRevision(int revision) + { + this.revision = revision; + } + + public int getCompression() + { + return compression; + } + + public void setCompression(int compression) + { + this.compression = compression; + } + + public FileData[] getFileData() + { + return fileData; + } + + public void setFileData(FileData[] fileData) + { + this.fileData = fileData; + } + + public byte[] getHash() + { + return hash; + } + + public void setHash(byte[] hash) + { + this.hash = hash; + } +} diff --git a/src/main/java/net/runelite/cache/fs/ArchiveFiles.java b/src/main/java/net/runelite/cache/fs/ArchiveFiles.java new file mode 100644 index 0000000..2642b1f --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/ArchiveFiles.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.fs; + +import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import net.runelite.cache.io.InputStream; +import net.runelite.cache.io.OutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ArchiveFiles +{ + private static final Logger logger = LoggerFactory.getLogger(ArchiveFiles.class); + + private final List files = new ArrayList<>(); + private final Map fileMap = new HashMap<>(); + + @Override + public int hashCode() + { + int hash = 7; + hash = 67 * hash + Objects.hashCode(this.files); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final ArchiveFiles other = (ArchiveFiles) obj; + if (!Objects.equals(this.files, other.files)) + { + return false; + } + return true; + } + + public void addFile(FSFile file) + { + Preconditions.checkArgument(file.getFileId() != -1); + + if (fileMap.containsKey(file.getFileId())) + { + throw new IllegalStateException("duplicate file ids"); + } + + files.add(file); + fileMap.put(file.getFileId(), file); + } + + public List getFiles() + { + return Collections.unmodifiableList(files); + } + + public FSFile findFile(int fileId) + { + return fileMap.get(fileId); + } + + public void clear() + { + files.clear(); + fileMap.clear(); + } + + public void loadContents(byte[] data) + { + logger.trace("Loading contents of archive ({} files)", files.size()); + + assert !this.getFiles().isEmpty(); + + if (this.getFiles().size() == 1) + { + this.getFiles().get(0).setContents(data); + return; + } + + int filesCount = this.getFiles().size(); + + InputStream stream = new InputStream(data); + stream.setOffset(stream.getLength() - 1); + int chunks = stream.readUnsignedByte(); + + // -1 for chunks count + one int per file slot per chunk + stream.setOffset(stream.getLength() - 1 - chunks * filesCount * 4); + int[][] chunkSizes = new int[filesCount][chunks]; + int[] filesSize = new int[filesCount]; + + for (int chunk = 0; chunk < chunks; ++chunk) + { + int chunkSize = 0; + + for (int id = 0; id < filesCount; ++id) + { + int delta = stream.readInt(); + chunkSize += delta; // size of this chunk + + chunkSizes[id][chunk] = chunkSize; // store size of chunk + + filesSize[id] += chunkSize; // add chunk size to file size + } + } + + byte[][] fileContents = new byte[filesCount][]; + int[] fileOffsets = new int[filesCount]; + + for (int i = 0; i < filesCount; ++i) + { + fileContents[i] = new byte[filesSize[i]]; + } + + // the file data is at the beginning of the stream + stream.setOffset(0); + + for (int chunk = 0; chunk < chunks; ++chunk) + { + for (int id = 0; id < filesCount; ++id) + { + int chunkSize = chunkSizes[id][chunk]; + + stream.readBytes(fileContents[id], fileOffsets[id], chunkSize); + + fileOffsets[id] += chunkSize; + } + } + + for (int i = 0; i < filesCount; ++i) + { + FSFile f = this.getFiles().get(i); + f.setContents(fileContents[i]); + } + } + + public byte[] saveContents() + { + OutputStream stream = new OutputStream(); + + int filesCount = this.getFiles().size(); + + if (filesCount == 1) + { + FSFile file = this.getFiles().get(0); + stream.writeBytes(file.getContents()); + } + else + { + for (FSFile file : this.getFiles()) + { + byte[] contents = file.getContents(); + stream.writeBytes(contents); + } + + int offset = 0; + + for (FSFile file : this.getFiles()) + { + int chunkSize = file.getSize(); + + int sz = chunkSize - offset; + offset = chunkSize; + stream.writeInt(sz); + } + + stream.writeByte(1); // chunks + } + + byte[] fileData = stream.flip(); + + logger.trace("Saved contents of archive ({} files), {} bytes", files.size(), fileData.length); + return fileData; + } +} diff --git a/src/main/java/net/runelite/cache/fs/Container.java b/src/main/java/net/runelite/cache/fs/Container.java new file mode 100644 index 0000000..9d57264 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/Container.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.fs; + +import static com.google.common.primitives.Bytes.concat; +import com.google.common.primitives.Ints; +import java.io.IOException; +import net.runelite.cache.fs.jagex.CompressionType; +import net.runelite.cache.io.InputStream; +import net.runelite.cache.io.OutputStream; +import net.runelite.cache.util.BZip2; +import net.runelite.cache.util.Crc32; +import net.runelite.cache.util.GZip; +import net.runelite.cache.util.Xtea; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Container +{ + private static final Logger logger = LoggerFactory.getLogger(Container.class); + + public byte[] data; + public int compression; // compression + public int revision; + public int crc; // crc of compressed data + + public Container(int compression, int revision) + { + this.compression = compression; + this.revision = revision; + } + + public void compress(byte[] data, int[] keys) throws IOException + { + OutputStream stream = new OutputStream(); + + byte[] compressedData; + int length; + switch (compression) + { + case CompressionType.NONE: + compressedData = data; + length = compressedData.length; + break; + case CompressionType.BZ2: + compressedData = concat(Ints.toByteArray(data.length), BZip2.compress(data)); + length = compressedData.length - 4; + break; + case CompressionType.GZ: + compressedData = concat(Ints.toByteArray(data.length), GZip.compress(data)); + length = compressedData.length - 4; + break; + default: + throw new RuntimeException("Unknown compression type"); + } + + compressedData = encrypt(compressedData, compressedData.length, keys); + + stream.writeByte(compression); + stream.writeInt(length); + + stream.writeBytes(compressedData); + if (revision != -1) + { + stream.writeShort(revision); + } + + this.data = stream.flip(); + } + + public static Container decompress(byte[] b, int[] keys) throws IOException + { + InputStream stream = new InputStream(b); + + int compression = stream.readUnsignedByte(); + int compressedLength = stream.readInt(); + if (compressedLength < 0 || compressedLength > 1000000) + { + throw new RuntimeException("Invalid data"); + } + + Crc32 crc32 = new Crc32(); + crc32.update(b, 0, 5); // compression + length + + byte[] data; + int revision = -1; + switch (compression) + { + case CompressionType.NONE: + { + byte[] encryptedData = new byte[compressedLength]; + stream.readBytes(encryptedData, 0, compressedLength); + + crc32.update(encryptedData, 0, compressedLength); + byte[] decryptedData = decrypt(encryptedData, encryptedData.length, keys); + + if (stream.remaining() >= 2) + { + revision = stream.readUnsignedShort(); + assert revision != -1; + } + + data = decryptedData; + + break; + } + case CompressionType.BZ2: + { + byte[] encryptedData = new byte[compressedLength + 4]; + stream.readBytes(encryptedData); + + crc32.update(encryptedData, 0, encryptedData.length); + byte[] decryptedData = decrypt(encryptedData, encryptedData.length, keys); + + if (stream.remaining() >= 2) + { + revision = stream.readUnsignedShort(); + assert revision != -1; + } + + stream = new InputStream(decryptedData); + + int decompressedLength = stream.readInt(); + data = BZip2.decompress(stream.getRemaining(), compressedLength); + + if (data == null) + { + return null; + } + + assert data.length == decompressedLength; + + break; + } + case CompressionType.GZ: + { + byte[] encryptedData = new byte[compressedLength + 4]; + stream.readBytes(encryptedData); + + crc32.update(encryptedData, 0, encryptedData.length); + byte[] decryptedData = decrypt(encryptedData, encryptedData.length, keys); + + if (stream.remaining() >= 2) + { + revision = stream.readUnsignedShort(); + assert revision != -1; + } + + stream = new InputStream(decryptedData); + + int decompressedLength = stream.readInt(); + data = GZip.decompress(stream.getRemaining(), compressedLength); + + if (data == null) + { + return null; + } + + assert data.length == decompressedLength; + + break; + } + default: + throw new RuntimeException("Unknown decompression type"); + } + + Container container = new Container(compression, revision); + container.data = data; + container.crc = crc32.getHash(); + return container; + } + + private static byte[] decrypt(byte[] data, int length, int[] keys) + { + if (keys == null) + { + return data; + } + + Xtea xtea = new Xtea(keys); + return xtea.decrypt(data, length); + } + + private static byte[] encrypt(byte[] data, int length, int[] keys) + { + if (keys == null) + { + return data; + } + + Xtea xtea = new Xtea(keys); + return xtea.encrypt(data, length); + } +} diff --git a/src/main/java/net/runelite/cache/fs/FSFile.java b/src/main/java/net/runelite/cache/fs/FSFile.java new file mode 100644 index 0000000..4046c40 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/FSFile.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.fs; + +import java.util.Arrays; + +public class FSFile +{ + private final int fileId; + private int nameHash; + private byte[] contents; + + public FSFile(int fileId) + { + this.fileId = fileId; + } + + @Override + public int hashCode() + { + int hash = 7; + hash = 97 * hash + this.fileId; + hash = 97 * hash + this.nameHash; + hash = 97 * hash + Arrays.hashCode(this.contents); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final FSFile other = (FSFile) obj; + if (this.fileId != other.fileId) + { + return false; + } + if (this.nameHash != other.nameHash) + { + return false; + } + if (!Arrays.equals(this.contents, other.contents)) + { + return false; + } + return true; + } + + public int getFileId() + { + return fileId; + } + + public int getNameHash() + { + return nameHash; + } + + public void setNameHash(int nameHash) + { + this.nameHash = nameHash; + } + + public byte[] getContents() + { + return contents; + } + + public void setContents(byte[] contents) + { + this.contents = contents; + } + + public int getSize() + { + return contents.length; + } +} diff --git a/src/main/java/net/runelite/cache/fs/Index.java b/src/main/java/net/runelite/cache/fs/Index.java new file mode 100644 index 0000000..6e915f9 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/Index.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.fs; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import net.runelite.cache.index.ArchiveData; +import net.runelite.cache.index.FileData; +import net.runelite.cache.index.IndexData; +import net.runelite.cache.util.Djb2; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Index +{ + private static final Logger logger = LoggerFactory.getLogger(Index.class); + + private final int id; + + private int protocol = 6; + private boolean named = true; + private int revision; + private int crc; + private int compression; // compression method of this index's data in 255 + + private final List archives = new ArrayList<>(); + + public Index(int id) + { + this.id = id; + } + + @Override + public int hashCode() + { + int hash = 3; + hash = 97 * hash + this.id; + hash = 97 * hash + this.revision; + hash = 97 * hash + Objects.hashCode(this.archives); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final Index other = (Index) obj; + if (this.id != other.id) + { + return false; + } + if (this.revision != other.revision) + { + return false; + } + if (!Objects.equals(this.archives, other.archives)) + { + return false; + } + return true; + } + + public int getId() + { + return id; + } + + public int getProtocol() + { + return protocol; + } + + public void setProtocol(int protocol) + { + this.protocol = protocol; + } + + public boolean isNamed() + { + return named; + } + + public void setNamed(boolean named) + { + this.named = named; + } + + public int getRevision() + { + return revision; + } + + public void setRevision(int revision) + { + this.revision = revision; + } + + public int getCrc() + { + return crc; + } + + public void setCrc(int crc) + { + this.crc = crc; + } + + public int getCompression() + { + return compression; + } + + public void setCompression(int compression) + { + this.compression = compression; + } + + public List getArchives() + { + return archives; + } + + public Archive addArchive(int id) + { + Archive archive = new Archive(this, id); + this.archives.add(archive); + return archive; + } + + public Archive getArchive(int id) + { + for (Archive a : archives) + { + if (a.getArchiveId() == id) + { + return a; + } + } + return null; + } + + public Archive findArchiveByName(String name) + { + int hash = Djb2.hash(name); + for (Archive a : archives) + { + if (a.getNameHash() == hash) + { + return a; + } + } + return null; + } + + public IndexData toIndexData() + { + IndexData data = new IndexData(); + data.setProtocol(protocol); + data.setRevision(revision); + data.setNamed(named); + + ArchiveData[] archiveDatas = new ArchiveData[archives.size()]; + data.setArchives(archiveDatas); + + int idx = 0; + for (Archive archive : archives) + { + ArchiveData ad = archiveDatas[idx++] = new ArchiveData(); + ad.setId(archive.getArchiveId()); + ad.setNameHash(archive.getNameHash()); + ad.setCrc(archive.getCrc()); + ad.setRevision(archive.getRevision()); + + FileData[] files = archive.getFileData(); + ad.setFiles(files); + } + return data; + } +} diff --git a/src/main/java/net/runelite/cache/fs/Storage.java b/src/main/java/net/runelite/cache/fs/Storage.java new file mode 100644 index 0000000..6bcdb88 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/Storage.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.fs; + +import java.io.IOException; + +public interface Storage extends AutoCloseable +{ + void init(Store store) throws IOException; + + @Override + void close() throws IOException; + + void load(Store store) throws IOException; + + void save(Store store) throws IOException; + + byte[] loadArchive(Archive archive) throws IOException; + + void saveArchive(Archive archive, byte[] data) throws IOException; +} diff --git a/src/main/java/net/runelite/cache/fs/Store.java b/src/main/java/net/runelite/cache/fs/Store.java new file mode 100644 index 0000000..6423a80 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/Store.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.fs; + +import java.io.Closeable; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import net.runelite.cache.IndexType; +import net.runelite.cache.fs.jagex.DiskStorage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class Store implements Closeable +{ + private static final Logger logger = LoggerFactory.getLogger(Store.class); + + private final Storage storage; + private final List indexes = new ArrayList<>(); + + public Store(File folder) throws IOException + { + storage = new DiskStorage(folder); + storage.init(this); + } + + public Store(Storage storage) throws IOException + { + this.storage = storage; + + storage.init(this); + } + + public Storage getStorage() + { + return storage; + } + + @Override + public void close() throws IOException + { + storage.close(); + } + + @Override + public int hashCode() + { + int hash = 5; + hash = 79 * hash + Objects.hashCode(this.indexes); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final Store other = (Store) obj; + if (!Objects.equals(this.indexes, other.indexes)) + { + return false; + } + return true; + } + + public final Index addIndex(int id) throws FileNotFoundException + { + for (Index i : indexes) + { + if (i.getId() == id) + { + throw new IllegalArgumentException("index " + id + " already exists"); + } + } + + Index index = new Index(id); + this.indexes.add(index); + + return index; + } + + public void removeIndex(Index index) + { + assert indexes.contains(index); + indexes.remove(index); + } + + public void load() throws IOException + { + storage.load(this); + } + + public void save() throws IOException + { + storage.save(this); + } + + public List getIndexes() + { + return indexes; + } + + public Index getIndex(IndexType type) + { + return findIndex(type.getNumber()); + } + + public Index findIndex(int id) + { + for (Index i : indexes) + { + if (i.getId() == id) + { + return i; + } + } + return null; + } +} diff --git a/src/main/java/net/runelite/cache/fs/flat/FlatStorage.java b/src/main/java/net/runelite/cache/fs/flat/FlatStorage.java new file mode 100644 index 0000000..8c5d7e7 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/flat/FlatStorage.java @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.fs.flat; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Base64; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; +import net.runelite.cache.index.FileData; + +/** + * A Storage that stores the cache as a series of flat files, designed + * to be git revisioned. + */ +public class FlatStorage implements Storage +{ + protected static final String EXTENSION = ".flatcache"; + + private final File directory; + private final Map data = new HashMap<>(); + + public FlatStorage(File directory) throws IOException + { + this.directory = directory; + } + + protected FlatStorage() + { + this.directory = null; + } + + protected InputStream openReader(String filename) throws IOException + { + return new FileInputStream(new File(directory, filename)); + } + + protected OutputStream openWriter(String filename) throws IOException + { + return new FileOutputStream(new File(directory, filename)); + } + + protected String[] listFlatcacheFiles() throws IOException + { + return directory.list((dir, name) -> name.endsWith(EXTENSION)); + } + + @Override + public void init(Store store) throws IOException + { + String[] idxs = listFlatcacheFiles(); + for (String idx : idxs) + { + int id = Integer.parseInt(idx.substring(0, idx.length() - EXTENSION.length())); + store.addIndex(id); + } + } + + @Override + public void close() throws IOException + { + } + + @Override + public void load(Store store) throws IOException + { + for (Index idx : store.getIndexes()) + { + String file = idx.getId() + EXTENSION; + try (BufferedReader br = new BufferedReader(new InputStreamReader(openReader(file)))) + { + int lineNo = 0; + Archive archive = null; + List fileData = null; + for (String line = br.readLine(); line != null; line = br.readLine()) + { + lineNo++; + + try + { + int lidx = line.indexOf('='); + String key = line.substring(0, lidx); + String value = line.substring(lidx + 1); + + if ("file".equals(key)) + { + if (fileData == null) + { + fileData = new ArrayList<>(); + } + + int vidx = value.indexOf('='); + FileData fd = new FileData(); + fd.setId(Integer.parseInt(value.substring(0, vidx))); + fd.setNameHash(Integer.parseInt(value.substring(vidx + 1))); + fileData.add(fd); + continue; + } + else if (fileData != null) + { + archive.setFileData(fileData.toArray(new FileData[0])); + fileData = null; + } + + if ("id".equals(key)) + { + archive = idx.addArchive(Integer.parseInt(value)); + continue; + } + + if (archive == null) + { + switch (key) + { + case "protocol": + idx.setProtocol(Integer.parseInt(value)); + continue; + case "revision": + idx.setRevision(Integer.parseInt(value)); + continue; + case "compression": + idx.setCompression(Integer.parseInt(value)); + continue; + case "crc": + idx.setCrc(Integer.parseInt(value)); + continue; + case "named": + idx.setNamed(Boolean.parseBoolean(value)); + continue; + } + } + else + { + switch (key) + { + case "namehash": + archive.setNameHash(Integer.parseInt(value)); + continue; + case "revision": + archive.setRevision(Integer.parseInt(value)); + continue; + case "crc": + archive.setCrc(Integer.parseInt(value)); + continue; + case "hash": + archive.setHash(Base64.getDecoder().decode(value)); + continue; + case "compression": + archive.setCompression(Integer.parseInt(value)); + continue; + case "contents": + data.put((long) idx.getId() << 32 | archive.getArchiveId(), Base64.getDecoder().decode(value)); + continue; + } + } + throw new IOException("unknown key: \"" + key + "\""); + } + catch (Exception e) + { + throw new IOException("error reading flatcache at " + file + ":" + lineNo, e); + } + } + + if (fileData != null) + { + archive.setFileData(fileData.toArray(new FileData[0])); + fileData = null; + } + } + } + } + + @Override + public void save(Store store) throws IOException + { + store.getIndexes().sort(Comparator.comparing(Index::getId)); + for (Index idx : store.getIndexes()) + { + String file = idx.getId() + EXTENSION; + try (PrintStream br = new PrintStream(openWriter(file))) + { + br.printf("protocol=%d\n", idx.getProtocol()); + br.printf("revision=%d\n", idx.getRevision()); + br.printf("compression=%d\n", idx.getCompression()); + br.printf("crc=%d\n", idx.getCrc()); + br.printf("named=%b\n", idx.getCompression()); + + idx.getArchives().sort(Comparator.comparing(Archive::getArchiveId)); + for (Archive archive : idx.getArchives()) + { + br.printf("id=%d\n", archive.getArchiveId()); + br.printf("namehash=%d\n", archive.getNameHash()); + br.printf("revision=%d\n", archive.getRevision()); + br.printf("crc=%d\n", archive.getCrc()); + + if (archive.getHash() != null) + { + br.append("hash="); + br.write(Base64.getEncoder().encode(archive.getHash())); + br.append("\n"); + } + + byte[] contents = store.getStorage().loadArchive(archive); + if (contents != null) + { + br.append("contents="); + br.write(Base64.getEncoder().encode(contents)); + br.append("\n"); + } + + br.printf("compression=%d\n", archive.getCompression()); + for (FileData fd : archive.getFileData()) + { + br.printf("file=%d=%d\n", fd.getId(), fd.getNameHash()); + } + } + } + } + } + + @Override + public byte[] loadArchive(Archive archive) throws IOException + { + return data.get((long) archive.getIndex().getId() << 32 | archive.getArchiveId()); + } + + @Override + public void saveArchive(Archive archive, byte[] bytes) throws IOException + { + data.put((long) archive.getIndex().getId() << 32 | archive.getArchiveId(), bytes); + } +} diff --git a/src/main/java/net/runelite/cache/fs/jagex/CompressionType.java b/src/main/java/net/runelite/cache/fs/jagex/CompressionType.java new file mode 100644 index 0000000..d11b3e2 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/jagex/CompressionType.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.fs.jagex; + +public class CompressionType +{ + public static final int NONE = 0; + public static final int BZ2 = 1; + public static final int GZ = 2; +} diff --git a/src/main/java/net/runelite/cache/fs/jagex/DataFile.java b/src/main/java/net/runelite/cache/fs/jagex/DataFile.java new file mode 100644 index 0000000..89eb607 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/jagex/DataFile.java @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.fs.jagex; + +import java.io.Closeable; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DataFile implements Closeable +{ + private static final Logger logger = LoggerFactory.getLogger(DataFile.class); + + private static final int SECTOR_SIZE = 520; + + private final RandomAccessFile dat; + + public DataFile(File file) throws FileNotFoundException + { + this.dat = new RandomAccessFile(file, "rw"); + } + + @Override + public void close() throws IOException + { + dat.close(); + } + + public void clear() throws IOException + { + dat.setLength(0L); + } + + /** + * + * @param indexId expected index of archive of contents being read + * @param archiveId expected archive of contents being read + * @param sector sector to start reading at + * @param size size of file + * @return + * @throws IOException + */ + public byte[] read(int indexId, int archiveId, int sector, int size) throws IOException + { + if (sector <= 0L || dat.length() / SECTOR_SIZE < (long) sector) + { + logger.warn("bad read, dat length {}, requested sector {}", dat.length(), sector); + return null; + } + + byte[] readBuffer = new byte[SECTOR_SIZE]; + ByteBuffer buffer = ByteBuffer.allocate(size); + + for (int part = 0, readBytesCount = 0, nextSector; + size > readBytesCount; + sector = nextSector) + { + if (sector == 0) + { + logger.warn("Unexpected end of file"); + return null; + } + + dat.seek(SECTOR_SIZE * sector); + + int dataBlockSize = size - readBytesCount; + byte headerSize; + int currentIndex; + int currentPart; + int currentArchive; + if (archiveId > 0xFFFF) + { + headerSize = 10; + if (dataBlockSize > SECTOR_SIZE - headerSize) + { + dataBlockSize = SECTOR_SIZE - headerSize; + } + + int i = dat.read(readBuffer, 0, headerSize + dataBlockSize); + if (i != headerSize + dataBlockSize) + { + logger.warn("Short read when reading file data for {}/{}", indexId, archiveId); + return null; + } + + currentArchive = ((readBuffer[0] & 0xFF) << 24) + | ((readBuffer[1] & 0xFF) << 16) + | ((readBuffer[2] & 0xFF) << 8) + | (readBuffer[3] & 0xFF); + currentPart = ((readBuffer[4] & 0xFF) << 8) + (readBuffer[5] & 0xFF); + nextSector = ((readBuffer[6] & 0xFF) << 16) + | ((readBuffer[7] & 0xFF) << 8) + | (readBuffer[8] & 0xFF); + currentIndex = readBuffer[9] & 0xFF; + } + else + { + headerSize = 8; + if (dataBlockSize > SECTOR_SIZE - headerSize) + { + dataBlockSize = SECTOR_SIZE - headerSize; + } + + int i = dat.read(readBuffer, 0, headerSize + dataBlockSize); + if (i != headerSize + dataBlockSize) + { + logger.warn("short read"); + return null; + } + + currentArchive = ((readBuffer[0] & 0xFF) << 8) + | (readBuffer[1] & 0xFF); + currentPart = ((readBuffer[2] & 0xFF) << 8) + | (readBuffer[3] & 0xFF); + nextSector = ((readBuffer[4] & 0xFF) << 16) + | ((readBuffer[5] & 0xFF) << 8) + | (readBuffer[6] & 0xFF); + currentIndex = readBuffer[7] & 0xFF; + } + + if (archiveId != currentArchive || currentPart != part || indexId != currentIndex) + { + logger.warn("data mismatch {} != {}, {} != {}, {} != {}", + archiveId, currentArchive, + part, currentPart, + indexId, currentIndex); + return null; + } + + if (nextSector < 0 || dat.length() / SECTOR_SIZE < (long) nextSector) + { + logger.warn("Invalid next sector"); + return null; + } + + buffer.put(readBuffer, headerSize, dataBlockSize); + readBytesCount += dataBlockSize; + + ++part; + } + + buffer.flip(); + return buffer.array(); + } + + public DataFileWriteResult write(int indexId, int archiveId, byte[] compressedData) throws IOException + { + int sector; + int startSector; + + byte[] writeBuffer = new byte[SECTOR_SIZE]; + ByteBuffer data = ByteBuffer.wrap(compressedData); + + sector = (int) ((dat.length() + (long) (SECTOR_SIZE - 1)) / (long) SECTOR_SIZE); + if (sector == 0) + { + sector = 1; + } + startSector = sector; + + for (int part = 0; data.hasRemaining(); ++part) + { + int nextSector = sector + 1; // we always just append sectors + int dataToWrite; + + if (0xFFFF < archiveId) + { + if (data.remaining() <= 510) + { + nextSector = 0; + } + + writeBuffer[0] = (byte) (archiveId >> 24); + writeBuffer[1] = (byte) (archiveId >> 16); + writeBuffer[2] = (byte) (archiveId >> 8); + writeBuffer[3] = (byte) archiveId; + writeBuffer[4] = (byte) (part >> 8); + writeBuffer[5] = (byte) part; + writeBuffer[6] = (byte) (nextSector >> 16); + writeBuffer[7] = (byte) (nextSector >> 8); + writeBuffer[8] = (byte) nextSector; + writeBuffer[9] = (byte) indexId; + dat.seek(SECTOR_SIZE * sector); + dat.write(writeBuffer, 0, 10); + + dataToWrite = data.remaining(); + if (dataToWrite > 510) + { + dataToWrite = 510; + } + } + else + { + if (data.remaining() <= 512) + { + nextSector = 0; + } + + writeBuffer[0] = (byte) (archiveId >> 8); + writeBuffer[1] = (byte) archiveId; + writeBuffer[2] = (byte) (part >> 8); + writeBuffer[3] = (byte) part; + writeBuffer[4] = (byte) (nextSector >> 16); + writeBuffer[5] = (byte) (nextSector >> 8); + writeBuffer[6] = (byte) nextSector; + writeBuffer[7] = (byte) indexId; + dat.seek(SECTOR_SIZE * sector); + dat.write(writeBuffer, 0, 8); + + dataToWrite = data.remaining(); + if (dataToWrite > 512) + { + dataToWrite = 512; + } + } + + data.get(writeBuffer, 0, dataToWrite); + dat.write(writeBuffer, 0, dataToWrite); + sector = nextSector; + } + + DataFileWriteResult res = new DataFileWriteResult(); + res.sector = startSector; + res.compressedLength = compressedData.length; + return res; + } +} diff --git a/src/main/java/net/runelite/cache/fs/jagex/DataFileWriteResult.java b/src/main/java/net/runelite/cache/fs/jagex/DataFileWriteResult.java new file mode 100644 index 0000000..7a7d651 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/jagex/DataFileWriteResult.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.fs.jagex; + +public class DataFileWriteResult +{ + public int sector, compressedLength; +} diff --git a/src/main/java/net/runelite/cache/fs/jagex/DiskStorage.java b/src/main/java/net/runelite/cache/fs/jagex/DiskStorage.java new file mode 100644 index 0000000..42fd8d9 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/jagex/DiskStorage.java @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.fs.jagex; + +import com.google.common.primitives.Ints; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.Container; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; +import net.runelite.cache.index.ArchiveData; +import net.runelite.cache.index.IndexData; +import net.runelite.cache.util.Crc32; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DiskStorage implements Storage +{ + private static final Logger logger = LoggerFactory.getLogger(DiskStorage.class); + + private static final String MAIN_FILE_CACHE_DAT = "main_file_cache.dat2"; + private static final String MAIN_FILE_CACHE_IDX = "main_file_cache.idx"; + + private final File folder; + + private final DataFile data; + private final IndexFile index255; + private final List indexFiles = new ArrayList<>(); + + public DiskStorage(File folder) throws IOException + { + this.folder = folder; + + this.data = new DataFile(new File(folder, MAIN_FILE_CACHE_DAT)); + this.index255 = new IndexFile(255, new File(folder, MAIN_FILE_CACHE_IDX + "255")); + } + + @Override + public void init(Store store) throws IOException + { + for (int i = 0; i < index255.getIndexCount(); ++i) + { + store.addIndex(i); + getIndex(i); + } + + assert store.getIndexes().size() == indexFiles.size(); + } + + @Override + public void close() throws IOException + { + data.close(); + index255.close(); + for (IndexFile indexFile : indexFiles) + { + indexFile.close(); + } + } + + private IndexFile getIndex(int i) throws FileNotFoundException + { + for (IndexFile indexFile : indexFiles) + { + if (indexFile.getIndexFileId() == i) + { + return indexFile; + } + } + + IndexFile indexFile = new IndexFile(i, new File(folder, MAIN_FILE_CACHE_IDX + i)); + indexFiles.add(indexFile); + return indexFile; + } + + @Override + public void load(Store store) throws IOException + { + for (Index index : store.getIndexes()) + { + loadIndex(index); + } + } + + public byte[] readIndex(int indexId) throws IOException + { + IndexEntry entry = index255.read(indexId); + if (entry != null) + { + byte[] indexData = data.read(index255.getIndexFileId(), entry.getId(), entry.getSector(), entry.getLength()); + return indexData; + } + + return null; + } + + private void loadIndex(Index index) throws IOException + { + logger.trace("Loading index {}", index.getId()); + + byte[] indexData = readIndex(index.getId()); + + if (indexData == null) + { + return; + } + + Container res = Container.decompress(indexData, null); + byte[] data = res.data; + + IndexData id = new IndexData(); + id.load(data); + + index.setProtocol(id.getProtocol()); + index.setRevision(id.getRevision()); + index.setNamed(id.isNamed()); + + for (ArchiveData ad : id.getArchives()) + { + Archive archive = index.addArchive(ad.getId()); + archive.setNameHash(ad.getNameHash()); + archive.setCrc(ad.getCrc()); + archive.setRevision(ad.getRevision()); + archive.setFileData(ad.getFiles()); + + assert ad.getFiles().length > 0; + } + + index.setCrc(res.crc); + index.setCompression(res.compression); + assert res.revision == -1; + } + + @Override + public byte[] loadArchive(Archive archive) throws IOException + { + Index index = archive.getIndex(); + IndexFile indexFile = getIndex(index.getId()); + + assert indexFile.getIndexFileId() == index.getId(); + + IndexEntry entry = indexFile.read(archive.getArchiveId()); + if (entry == null) + { + logger.debug("can't read archive " + archive.getArchiveId() + " from index " + index.getId()); + return null; + } + + assert entry.getId() == archive.getArchiveId(); + + logger.trace("Loading archive {} for index {} from sector {} length {}", + archive.getArchiveId(), index.getId(), entry.getSector(), entry.getLength()); + + byte[] archiveData = data.read(index.getId(), entry.getId(), entry.getSector(), entry.getLength()); + return archiveData; + } + + @Override + public void save(Store store) throws IOException + { + logger.debug("Saving store"); + + for (Index i : store.getIndexes()) + { + saveIndex(i); + } + } + + private void saveIndex(Index index) throws IOException + { + IndexData indexData = index.toIndexData(); + byte[] data = indexData.writeIndexData(); + + Container container = new Container(index.getCompression(), -1); // index data revision is always -1 + container.compress(data, null); + byte[] compressedData = container.data; + DataFileWriteResult res = this.data.write(index255.getIndexFileId(), index.getId(), compressedData); + + index255.write(new IndexEntry(index255, index.getId(), res.sector, res.compressedLength)); + + Crc32 crc = new Crc32(); + crc.update(compressedData, 0, compressedData.length); + index.setCrc(crc.getHash()); + } + + @Override + public void saveArchive(Archive a, byte[] archiveData) throws IOException + { + Index index = a.getIndex(); + IndexFile indexFile = getIndex(index.getId()); + assert indexFile.getIndexFileId() == index.getId(); + + DataFileWriteResult res = data.write(index.getId(), a.getArchiveId(), archiveData); + indexFile.write(new IndexEntry(indexFile, a.getArchiveId(), res.sector, res.compressedLength)); + + byte compression = archiveData[0]; + int compressedSize = Ints.fromBytes(archiveData[1], archiveData[2], + archiveData[3], archiveData[4]); + + // don't crc the appended revision, if it is there + int length = 1 // compression type + + 4 // compressed size + + compressedSize + + (compression != CompressionType.NONE ? 4 : 0); + + Crc32 crc = new Crc32(); + crc.update(archiveData, 0, length); + a.setCrc(crc.getHash()); + + logger.trace("Saved archive {}/{} at sector {}, compressed length {}", + index.getId(), a.getArchiveId(), res.sector, res.compressedLength); + } +} diff --git a/src/main/java/net/runelite/cache/fs/jagex/IndexEntry.java b/src/main/java/net/runelite/cache/fs/jagex/IndexEntry.java new file mode 100644 index 0000000..c41e223 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/jagex/IndexEntry.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.fs.jagex; + +import java.util.Objects; + +public class IndexEntry +{ + private final IndexFile indexFile; + private final int id, sector, length; + + public IndexEntry(IndexFile indexFile, int id, int sector, int length) + { + this.indexFile = indexFile; + this.id = id; + this.sector = sector; + this.length = length; + } + + public IndexFile getIndexFile() + { + return indexFile; + } + + public int getId() + { + return id; + } + + public int getSector() + { + return sector; + } + + public int getLength() + { + return length; + } + + @Override + public int hashCode() + { + int hash = 7; + hash = 19 * hash + Objects.hashCode(this.indexFile); + hash = 19 * hash + this.id; + hash = 19 * hash + this.sector; + hash = 19 * hash + this.length; + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final IndexEntry other = (IndexEntry) obj; + if (!Objects.equals(this.indexFile, other.indexFile)) + { + return false; + } + if (this.id != other.id) + { + return false; + } + if (this.sector != other.sector) + { + return false; + } + if (this.length != other.length) + { + return false; + } + return true; + } +} diff --git a/src/main/java/net/runelite/cache/fs/jagex/IndexFile.java b/src/main/java/net/runelite/cache/fs/jagex/IndexFile.java new file mode 100644 index 0000000..b95ae70 --- /dev/null +++ b/src/main/java/net/runelite/cache/fs/jagex/IndexFile.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.fs.jagex; + +import java.io.Closeable; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Objects; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class IndexFile implements Closeable +{ + private static final Logger logger = LoggerFactory.getLogger(IndexFile.class); + + private static final int INDEX_ENTRY_LEN = 6; + + private final int indexFileId; + private final File file; + private final RandomAccessFile idx; + private final byte[] buffer = new byte[INDEX_ENTRY_LEN]; + + public IndexFile(int indexFileId, File file) throws FileNotFoundException + { + this.indexFileId = indexFileId; + this.file = file; + this.idx = new RandomAccessFile(file, "rw"); + } + + @Override + public void close() throws IOException + { + idx.close(); + } + + public void clear() throws IOException + { + idx.setLength(0L); + } + + @Override + public int hashCode() + { + int hash = 3; + hash = 41 * hash + Objects.hashCode(this.file); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final IndexFile other = (IndexFile) obj; + if (!Objects.equals(this.file, other.file)) + { + return false; + } + return true; + } + + public int getIndexFileId() + { + return indexFileId; + } + + public synchronized void write(IndexEntry entry) throws IOException + { + idx.seek(entry.getId() * INDEX_ENTRY_LEN); + + buffer[0] = (byte) (entry.getLength() >> 16); + buffer[1] = (byte) (entry.getLength() >> 8); + buffer[2] = (byte) entry.getLength(); + + buffer[3] = (byte) (entry.getSector() >> 16); + buffer[4] = (byte) (entry.getSector() >> 8); + buffer[5] = (byte) entry.getSector(); + + idx.write(buffer); + } + + public synchronized IndexEntry read(int id) throws IOException + { + idx.seek(id * INDEX_ENTRY_LEN); + int i = idx.read(buffer); + if (i != INDEX_ENTRY_LEN) + { + logger.debug("short read for id {} on index {}: {}", id, indexFileId, i); + return null; + } + + int length = ((buffer[0] & 0xFF) << 16) | ((buffer[1] & 0xFF) << 8) | (buffer[2] & 0xFF); + int sector = ((buffer[3] & 0xFF) << 16) | ((buffer[4] & 0xFF) << 8) | (buffer[5] & 0xFF); + + if (length <= 0 || sector <= 0) + { + logger.debug("invalid length or sector {}/{}", length, sector); + return null; + } + + return new IndexEntry(this, id, sector, length); + } + + public synchronized int getIndexCount() throws IOException + { + return (int) (idx.length() / INDEX_ENTRY_LEN); + } +} diff --git a/src/main/java/net/runelite/cache/index/ArchiveData.java b/src/main/java/net/runelite/cache/index/ArchiveData.java new file mode 100644 index 0000000..4bc4427 --- /dev/null +++ b/src/main/java/net/runelite/cache/index/ArchiveData.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.index; + +public class ArchiveData +{ + int id; + int nameHash; + int crc; + int revision; + FileData[] files; + + public int getId() + { + return id; + } + + public void setId(int id) + { + this.id = id; + } + + public int getNameHash() + { + return nameHash; + } + + public void setNameHash(int nameHash) + { + this.nameHash = nameHash; + } + + public int getCrc() + { + return crc; + } + + public void setCrc(int crc) + { + this.crc = crc; + } + + public int getRevision() + { + return revision; + } + + public void setRevision(int revision) + { + this.revision = revision; + } + + public FileData[] getFiles() + { + return files; + } + + public void setFiles(FileData[] files) + { + this.files = files; + } +} diff --git a/src/main/java/net/runelite/cache/index/FileData.java b/src/main/java/net/runelite/cache/index/FileData.java new file mode 100644 index 0000000..dfe8f41 --- /dev/null +++ b/src/main/java/net/runelite/cache/index/FileData.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.index; + +public class FileData +{ + int id; + int nameHash; + + public int getId() + { + return id; + } + + public void setId(int id) + { + this.id = id; + } + + public int getNameHash() + { + return nameHash; + } + + public void setNameHash(int nameHash) + { + this.nameHash = nameHash; + } +} diff --git a/src/main/java/net/runelite/cache/index/IndexData.java b/src/main/java/net/runelite/cache/index/IndexData.java new file mode 100644 index 0000000..38747bd --- /dev/null +++ b/src/main/java/net/runelite/cache/index/IndexData.java @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.index; + +import net.runelite.cache.io.InputStream; +import net.runelite.cache.io.OutputStream; + +public class IndexData +{ + private int protocol; + private int revision; + private boolean named; + private ArchiveData[] archives; + + public void load(byte[] data) + { + InputStream stream = new InputStream(data); + protocol = stream.readUnsignedByte(); + if (protocol < 5 || protocol > 7) + { + throw new IllegalArgumentException("Unsupported protocol"); + } + + if (protocol >= 6) + { + this.revision = stream.readInt(); + } + + int hash = stream.readUnsignedByte(); + named = (1 & hash) != 0; + if ((hash & ~1) != 0) + { + throw new IllegalArgumentException("Unknown flags"); + } + assert (hash & ~3) == 0; + int validArchivesCount = protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); + int lastArchiveId = 0; + + archives = new ArchiveData[validArchivesCount]; + + for (int index = 0; index < validArchivesCount; ++index) + { + int archive = lastArchiveId += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); + + ArchiveData ad = new ArchiveData(); + ad.id = archive; + archives[index] = ad; + } + + if (named) + { + for (int index = 0; index < validArchivesCount; ++index) + { + int nameHash = stream.readInt(); + ArchiveData ad = archives[index]; + ad.nameHash = nameHash; + } + } + + for (int index = 0; index < validArchivesCount; ++index) + { + int crc = stream.readInt(); + + ArchiveData ad = archives[index]; + ad.crc = crc; + } + + for (int index = 0; index < validArchivesCount; ++index) + { + int revision = stream.readInt(); + + ArchiveData ad = archives[index]; + ad.revision = revision; + } + + int[] numberOfFiles = new int[validArchivesCount]; + for (int index = 0; index < validArchivesCount; ++index) + { + int num = protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); + numberOfFiles[index] = num; + } + + for (int index = 0; index < validArchivesCount; ++index) + { + ArchiveData ad = archives[index]; + int num = numberOfFiles[index]; + + ad.files = new FileData[num]; + + int last = 0; + for (int i = 0; i < num; ++i) + { + int fileId = last += protocol >= 7 ? stream.readBigSmart() : stream.readUnsignedShort(); + + FileData fd = ad.files[i] = new FileData(); + fd.id = fileId; + } + } + + if (named) + { + for (int index = 0; index < validArchivesCount; ++index) + { + ArchiveData ad = archives[index]; + int num = numberOfFiles[index]; + + for (int i = 0; i < num; ++i) + { + FileData fd = ad.files[i]; + int name = stream.readInt(); + fd.nameHash = name; + } + } + } + } + + public byte[] writeIndexData() + { + OutputStream stream = new OutputStream(); + stream.writeByte(protocol); + if (protocol >= 6) + { + stream.writeInt(this.revision); + } + + stream.writeByte(named ? 1 : 0); + if (protocol >= 7) + { + stream.writeBigSmart(this.archives.length); + } + else + { + stream.writeShort(this.archives.length); + } + + for (int i = 0; i < this.archives.length; ++i) + { + ArchiveData a = this.archives[i]; + int archive = a.getId(); + + if (i != 0) + { + ArchiveData prev = this.archives[i - 1]; + archive -= prev.getId(); + } + + if (protocol >= 7) + { + stream.writeBigSmart(archive); + } + else + { + stream.writeShort(archive); + } + } + + if (named) + { + for (int i = 0; i < this.archives.length; ++i) + { + ArchiveData a = this.archives[i]; + stream.writeInt(a.getNameHash()); + } + } + + for (int i = 0; i < this.archives.length; ++i) + { + ArchiveData a = this.archives[i]; + stream.writeInt(a.getCrc()); + } + + for (int i = 0; i < this.archives.length; ++i) + { + ArchiveData a = this.archives[i]; + stream.writeInt(a.getRevision()); + } + + for (int i = 0; i < this.archives.length; ++i) + { + ArchiveData a = this.archives[i]; + + int len = a.getFiles().length; + + if (protocol >= 7) + { + stream.writeBigSmart(len); + } + else + { + stream.writeShort(len); + } + } + + for (int i = 0; i < this.archives.length; ++i) + { + ArchiveData a = this.archives[i]; + + for (int j = 0; j < a.getFiles().length; ++j) + { + FileData file = a.getFiles()[j]; + int offset = file.getId(); + + if (j != 0) + { + FileData prev = a.getFiles()[j - 1]; + offset -= prev.getId(); + } + + if (protocol >= 7) + { + stream.writeBigSmart(offset); + } + else + { + stream.writeShort(offset); + } + } + } + + if (named) + { + for (int i = 0; i < this.archives.length; ++i) + { + ArchiveData a = this.archives[i]; + + for (int j = 0; j < a.getFiles().length; ++j) + { + FileData file = a.getFiles()[j]; + stream.writeInt(file.getNameHash()); + } + } + } + + return stream.flip(); + } + + public int getProtocol() + { + return protocol; + } + + public void setProtocol(int protocol) + { + this.protocol = protocol; + } + + public int getRevision() + { + return revision; + } + + public void setRevision(int revision) + { + this.revision = revision; + } + + public boolean isNamed() + { + return named; + } + + public void setNamed(boolean named) + { + this.named = named; + } + + public ArchiveData[] getArchives() + { + return archives; + } + + public void setArchives(ArchiveData[] archives) + { + this.archives = archives; + } +} diff --git a/src/main/java/net/runelite/cache/io/InputStream.java b/src/main/java/net/runelite/cache/io/InputStream.java new file mode 100644 index 0000000..1fde0d9 --- /dev/null +++ b/src/main/java/net/runelite/cache/io/InputStream.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.io; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public class InputStream extends java.io.InputStream +{ + private static final char[] CHARACTERS = new char[] + { + '\u20ac', '\u0000', '\u201a', '\u0192', '\u201e', '\u2026', + '\u2020', '\u2021', '\u02c6', '\u2030', '\u0160', '\u2039', + '\u0152', '\u0000', '\u017d', '\u0000', '\u0000', '\u2018', + '\u2019', '\u201c', '\u201d', '\u2022', '\u2013', '\u2014', + '\u02dc', '\u2122', '\u0161', '\u203a', '\u0153', '\u0000', + '\u017e', '\u0178' + }; + + private final ByteBuffer buffer; + + public InputStream(byte[] buffer) + { + this.buffer = ByteBuffer.wrap(buffer); + } + + public byte[] getArray() + { + assert buffer.hasArray(); + return buffer.array(); + } + + @Override + public String toString() + { + return "InputStream{" + "buffer=" + buffer + '}'; + } + + public int read24BitInt() + { + return (this.readUnsignedByte() << 16) + (this.readUnsignedByte() << 8) + this.readUnsignedByte(); + } + + public void skip(int length) + { + int pos = buffer.position(); + pos += length; + buffer.position(pos); + } + + public void setOffset(int offset) + { + buffer.position(offset); + } + + public int getOffset() + { + return buffer.position(); + } + + public int getLength() + { + return buffer.limit(); + } + + public int remaining() + { + return buffer.remaining(); + } + + public byte readByte() + { + return buffer.get(); + } + + public void readBytes(byte[] buffer, int off, int len) + { + this.buffer.get(buffer, off, len); + } + + public void readBytes(byte[] buffer) + { + this.buffer.get(buffer); + } + + public int readUnsignedByte() + { + return this.readByte() & 0xFF; + } + + public int readUnsignedShort() + { + return buffer.getShort() & 0xFFFF; + } + + public short readShort() + { + return buffer.getShort(); + } + + public int readInt() + { + return buffer.getInt(); + } + + public byte peek() + { + return buffer.get(buffer.position()); + } + + public int readBigSmart() + { + return peek() >= 0 ? (this.readUnsignedShort() & 0xFFFF) : (this.readInt() & Integer.MAX_VALUE); + } + + public int readBigSmart2() + { + if (peek() < 0) + { + return readInt() & Integer.MAX_VALUE; // and off sign bit + } + int value = readUnsignedShort(); + return value == 32767 ? -1 : value; + } + + public int readShortSmart() + { + int peek = this.peek() & 0xFF; + return peek < 128 ? this.readUnsignedByte() - 64 : this.readUnsignedShort() - 0xc000; + } + + public int readUnsignedShortSmart() + { + int peek = this.peek() & 0xFF; + return peek < 128 ? this.readUnsignedByte() : this.readUnsignedShort() - 0x8000; + } + + public int readUnsignedIntSmartShortCompat() + { + int var1 = 0; + + int var2; + for (var2 = this.readUnsignedShortSmart(); var2 == 32767; var2 = this.readUnsignedShortSmart()) + { + var1 += 32767; + } + + var1 += var2; + return var1; + } + + public String readString() + { + StringBuilder sb = new StringBuilder(); + + for (; ; ) + { + int ch = this.readUnsignedByte(); + + if (ch == 0) + { + break; + } + + if (ch >= 128 && ch < 160) + { + char var7 = CHARACTERS[ch - 128]; + if (0 == var7) + { + var7 = '?'; + } + + ch = var7; + } + + sb.append((char) ch); + } + return sb.toString(); + } + + public String readStringOrNull() + { + if (this.peek() != 0) + { + return readString(); + } + else + { + this.readByte(); // discard + return null; + } + } + + public int readVarInt() + { + byte var1 = this.readByte(); + + int var2; + for (var2 = 0; var1 < 0; var1 = this.readByte()) + { + var2 = (var2 | var1 & 127) << 7; + } + + return var2 | var1; + } + + public byte[] getRemaining() + { + byte[] b = new byte[buffer.remaining()]; + buffer.get(b); + return b; + } + + @Override + public int read() throws IOException + { + return this.readUnsignedByte(); + } +} diff --git a/src/main/java/net/runelite/cache/io/OutputStream.java b/src/main/java/net/runelite/cache/io/OutputStream.java new file mode 100644 index 0000000..537c6bb --- /dev/null +++ b/src/main/java/net/runelite/cache/io/OutputStream.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.io; + +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; + +public final class OutputStream extends java.io.OutputStream +{ + private ByteBuffer buffer; + + public OutputStream(int capacity) + { + buffer = ByteBuffer.allocate(capacity); + } + + public OutputStream() + { + this(16); + } + + public byte[] getArray() + { + assert buffer.hasArray(); + return buffer.array(); + } + + private void ensureRemaining(int remaining) + { + while (remaining > buffer.remaining()) + { + int newCapacity = buffer.capacity() * 2; + + ByteBuffer old = buffer; + old.flip(); + + buffer = ByteBuffer.allocate(newCapacity); + + buffer.put(old); + } + } + + public void skip(int length) + { + int pos = buffer.position(); + pos += length; + buffer.position(pos); + } + + public int getOffset() + { + return buffer.position(); + } + + public void setOffset(int offset) + { + buffer.position(offset); + } + + public void writeBytes(byte[] b) + { + writeBytes(b, 0, b.length); + } + + public void writeBytes(byte[] b, int offset, int length) + { + ensureRemaining(length); + buffer.put(b, offset, length); + } + + public void writeByte(int i) + { + ensureRemaining(1); + buffer.put((byte) i); + } + + public void writeBigSmart(int value) + { + Preconditions.checkArgument(value >= 0); + if (value >= 32768) + { + ensureRemaining(4); + this.writeInt((1 << 31) | value); + } + else + { + ensureRemaining(2); + this.writeShort(value); + } + } + + public void writeShort(int i) + { + ensureRemaining(2); + buffer.putShort((short) i); + } + + public void writeShortSmart(int value) + { + Preconditions.checkArgument(value >= 0); + if (value < 128) + { + writeByte(value); + } + else + { + writeShort(0x8000 | value); + } + } + + public void write24BitInt(int i) + { + ensureRemaining(3); + buffer.put((byte) (i >>> 16)); + buffer.put((byte) (i >>> 8)); + buffer.put((byte) (i & 0xFF)); + } + + public void writeInt(int i) + { + ensureRemaining(4); + buffer.putInt(i); + } + + public void writeVarInt(int var1) + { + if ((var1 & -128) != 0) + { + if ((var1 & -16384) != 0) + { + if ((var1 & -2097152) != 0) + { + if ((var1 & -268435456) != 0) + { + this.writeByte(var1 >>> 28 | 128); + } + + this.writeByte(var1 >>> 21 | 128); + } + + this.writeByte(var1 >>> 14 | 128); + } + + this.writeByte(var1 >>> 7 | 128); + } + + this.writeByte(var1 & 127); + } + + public void writeLengthFromMark(int var1) + { + this.getArray()[this.getOffset() - var1 - 4] = (byte) (var1 >> 24); + this.getArray()[this.getOffset() - var1 - 3] = (byte) (var1 >> 16); + this.getArray()[this.getOffset() - var1 - 2] = (byte) (var1 >> 8); + this.getArray()[this.getOffset() - var1 - 1] = (byte) var1; + } + + public void writeString(String str) + { + Charset utf8charset = Charset.forName("UTF-8"); + Charset cp1252charset = Charset.forName("Cp1252"); + + ByteBuffer inputBuffer = ByteBuffer.wrap(str.getBytes()); + + CharBuffer data = utf8charset.decode(inputBuffer); + + ByteBuffer outputBuffer = cp1252charset.encode(data); + byte[] outputData = outputBuffer.array(); + + writeBytes(outputData); + writeByte(0); + } + + public byte[] flip() + { + ((Buffer) buffer).flip(); + byte[] b = new byte[buffer.limit()]; + buffer.get(b); + return b; + } + + @Override + public void write(int b) throws IOException + { + buffer.put((byte) b); + } + +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/item/ColorPalette.java b/src/main/java/net/runelite/cache/item/ColorPalette.java new file mode 100644 index 0000000..6486afe --- /dev/null +++ b/src/main/java/net/runelite/cache/item/ColorPalette.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.item; + +import lombok.Getter; + +public class ColorPalette +{ + @Getter + private final int[] colorPalette; + + public ColorPalette(double brightness, int var2, int var3) + { + colorPalette = buildColorPalettee(brightness, var2, var3); + } + + private int[] buildColorPalettee(double brightness, int var2, int var3) + { + int[] colorPalette = new int[65536]; + int var4 = var2 * 128; + + for (int var5 = var2; var5 < var3; ++var5) + { + double var6 = (double) (var5 >> 3) / 64.0D + 0.0078125D; + double var8 = (double) (var5 & 7) / 8.0D + 0.0625D; + + for (int var10 = 0; var10 < 128; ++var10) + { + double var11 = (double) var10 / 128.0D; + double var13 = var11; + double var15 = var11; + double var17 = var11; + if (var8 != 0.0D) + { + double var19; + if (var11 < 0.5D) + { + var19 = var11 * (1.0D + var8); + } + else + { + var19 = var11 + var8 - var11 * var8; + } + + double var21 = 2.0D * var11 - var19; + double var23 = var6 + 0.3333333333333333D; + if (var23 > 1.0D) + { + --var23; + } + + double var27 = var6 - 0.3333333333333333D; + if (var27 < 0.0D) + { + ++var27; + } + + if (6.0D * var23 < 1.0D) + { + var13 = var21 + (var19 - var21) * 6.0D * var23; + } + else if (2.0D * var23 < 1.0D) + { + var13 = var19; + } + else if (3.0D * var23 < 2.0D) + { + var13 = var21 + (var19 - var21) * (0.6666666666666666D - var23) * 6.0D; + } + else + { + var13 = var21; + } + + if (6.0D * var6 < 1.0D) + { + var15 = var21 + (var19 - var21) * 6.0D * var6; + } + else if (2.0D * var6 < 1.0D) + { + var15 = var19; + } + else if (3.0D * var6 < 2.0D) + { + var15 = var21 + (var19 - var21) * (0.6666666666666666D - var6) * 6.0D; + } + else + { + var15 = var21; + } + + if (6.0D * var27 < 1.0D) + { + var17 = var21 + (var19 - var21) * 6.0D * var27; + } + else if (2.0D * var27 < 1.0D) + { + var17 = var19; + } + else if (3.0D * var27 < 2.0D) + { + var17 = var21 + (var19 - var21) * (0.6666666666666666D - var27) * 6.0D; + } + else + { + var17 = var21; + } + } + + int var29 = (int) (var13 * 256.0D); + int var20 = (int) (var15 * 256.0D); + int var30 = (int) (var17 * 256.0D); + int var22 = var30 + (var20 << 8) + (var29 << 16); + var22 = adjustRGB(var22, brightness); + if (var22 == 0) + { + var22 = 1; + } + + colorPalette[var4++] = var22; + } + } + return colorPalette; + } + + private static int adjustRGB(int var0, double var1) + { + double var3 = (double) (var0 >> 16) / 256.0D; + double var5 = (double) (var0 >> 8 & 255) / 256.0D; + double var7 = (double) (var0 & 255) / 256.0D; + var3 = Math.pow(var3, var1); + var5 = Math.pow(var5, var1); + var7 = Math.pow(var7, var1); + int var9 = (int) (var3 * 256.0D); + int var10 = (int) (var5 * 256.0D); + int var11 = (int) (var7 * 256.0D); + return var11 + (var10 << 8) + (var9 << 16); + } +} diff --git a/src/main/java/net/runelite/cache/item/Graphics3D.java b/src/main/java/net/runelite/cache/item/Graphics3D.java new file mode 100644 index 0000000..248ab6c --- /dev/null +++ b/src/main/java/net/runelite/cache/item/Graphics3D.java @@ -0,0 +1,2818 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.item; + +class Graphics3D extends Rasterizer2D +{ + private static final double UNIT = Math.PI / 1024d; // How much of the circle each unit of SINE/COSINE is + + public static final int[] SINE = new int[2048]; // sine angles for each of the 2048 units, * 65536 and stored as an int + public static final int[] COSINE = new int[2048]; // cosine + + private static int[] field1932 = new int[512]; + static int[] field1933 = new int[2048]; + + static + { + for (int i = 0; i < 2048; ++i) + { + SINE[i] = (int) (65536.0D * Math.sin((double) i * UNIT)); + COSINE[i] = (int) (65536.0D * Math.cos((double) i * UNIT)); + } + + int var0; + for (var0 = 1; var0 < 512; ++var0) + { + field1932[var0] = 32768 / var0; + } + + for (var0 = 1; var0 < 2048; ++var0) + { + field1933[var0] = 65536 / var0; + } + } + + private final RSTextureProvider textureProvider; + boolean rasterClipEnable; + boolean field1909; + boolean lowMem; + public boolean rasterGouraudLowRes = true; + int rasterAlpha; + public int Rasterizer3D_zoom = 512; + int centerX; + int centerY; + int rasterClipX; + int Rasterizer3D_clipHeight; + int Rasterizer3D_clipNegativeMidX; + int Rasterizer3D_clipMidX2; + int Rasterizer3D_clipNegativeMidY; + int Rasterizer3D_clipMidY2; + int[] rasterClipY = new int[1024]; + public int[] colorPalette; + + public Graphics3D(RSTextureProvider textureProvider) + { + this.textureProvider = textureProvider; + } + + public final void setRasterClipping() + { + setRasterClipping(draw_region_x, drawingAreaTop, drawingAreaRight, drawingAreaBottom); + } + + final void setRasterClipping(int var0, int var1, int var2, int var3) + { + rasterClipX = var2 - var0; + Rasterizer3D_clipHeight = var3 - var1; + Rasterizer3D_method3(); + + if (rasterClipY.length < Rasterizer3D_clipHeight) + { + // Find closest 2^n >= v + int v = Rasterizer3D_clipHeight - 1; + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + rasterClipY = new int[v + 1]; + } + + int var4 = var0 + graphicsPixelsWidth * var1; + for (int i = 0; i < Rasterizer3D_clipHeight; ++i) + { + rasterClipY[i] = var4; + var4 += graphicsPixelsWidth; + } + + } + + public final void Rasterizer3D_method3() + { + centerX = rasterClipX / 2; + centerY = Rasterizer3D_clipHeight / 2; + Rasterizer3D_clipNegativeMidX = -centerX; + Rasterizer3D_clipMidX2 = rasterClipX - centerX; + Rasterizer3D_clipNegativeMidY = -centerY; + Rasterizer3D_clipMidY2 = Rasterizer3D_clipHeight - centerY; + } + + public final void setOffset(int x, int y) + { + int var2 = rasterClipY[0]; + int var3 = var2 / graphicsPixelsWidth; + int var4 = var2 - var3 * graphicsPixelsWidth; + centerX = x - var4; + centerY = y - var3; + Rasterizer3D_clipNegativeMidX = -centerX; + Rasterizer3D_clipMidX2 = rasterClipX - centerX; + Rasterizer3D_clipNegativeMidY = -centerY; + Rasterizer3D_clipMidY2 = Rasterizer3D_clipHeight - centerY; + } + + public final void setBrightness(double var0) + { + colorPalette = new ColorPalette(var0, 0, 512).getColorPalette(); + } + + final void rasterGouraud(int var0, int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8) + { + int var9 = var4 - var3; + int var10 = var1 - var0; + int var11 = var5 - var3; + int var12 = var2 - var0; + int var13 = var7 - var6; + int var14 = var8 - var6; + int var15; + if (var2 != var1) + { + var15 = (var5 - var4 << 14) / (var2 - var1); + } + else + { + var15 = 0; + } + + int var16; + if (var0 != var1) + { + var16 = (var9 << 14) / var10; + } + else + { + var16 = 0; + } + + int var17; + if (var0 != var2) + { + var17 = (var11 << 14) / var12; + } + else + { + var17 = 0; + } + + int var18 = var9 * var12 - var11 * var10; + if (var18 != 0) + { + int var19 = (var13 * var12 - var14 * var10 << 8) / var18; + int var20 = (var14 * var9 - var13 * var11 << 8) / var18; + if (var0 <= var1 && var0 <= var2) + { + if (var0 < Rasterizer3D_clipHeight) + { + if (var1 > Rasterizer3D_clipHeight) + { + var1 = Rasterizer3D_clipHeight; + } + + if (var2 > Rasterizer3D_clipHeight) + { + var2 = Rasterizer3D_clipHeight; + } + + var6 = var19 + ((var6 << 8) - var3 * var19); + if (var1 < var2) + { + var5 = var3 <<= 14; + if (var0 < 0) + { + var5 -= var0 * var17; + var3 -= var0 * var16; + var6 -= var0 * var20; + var0 = 0; + } + + var4 <<= 14; + if (var1 < 0) + { + var4 -= var15 * var1; + var1 = 0; + } + + if (var0 != var1 && var17 < var16 || var0 == var1 && var17 > var15) + { + var2 -= var1; + var1 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2778(graphicsPixels, var0, 0, 0, var5 >> 14, var4 >> 14, var6, var19); + var5 += var17; + var4 += var15; + var6 += var20; + var0 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var0, 0, 0, var5 >> 14, var3 >> 14, var6, var19); + var5 += var17; + var3 += var16; + var6 += var20; + var0 += graphicsPixelsWidth; + } + } + else + { + var2 -= var1; + var1 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2778(graphicsPixels, var0, 0, 0, var4 >> 14, var5 >> 14, var6, var19); + var5 += var17; + var4 += var15; + var6 += var20; + var0 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var0, 0, 0, var3 >> 14, var5 >> 14, var6, var19); + var5 += var17; + var3 += var16; + var6 += var20; + var0 += graphicsPixelsWidth; + } + } + } + else + { + var4 = var3 <<= 14; + if (var0 < 0) + { + var4 -= var0 * var17; + var3 -= var0 * var16; + var6 -= var0 * var20; + var0 = 0; + } + + var5 <<= 14; + if (var2 < 0) + { + var5 -= var15 * var2; + var2 = 0; + } + + if (var0 != var2 && var17 < var16 || var0 == var2 && var15 > var16) + { + var1 -= var2; + var2 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2778(graphicsPixels, var0, 0, 0, var5 >> 14, var3 >> 14, var6, var19); + var5 += var15; + var3 += var16; + var6 += var20; + var0 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var0, 0, 0, var4 >> 14, var3 >> 14, var6, var19); + var4 += var17; + var3 += var16; + var6 += var20; + var0 += graphicsPixelsWidth; + } + } + else + { + var1 -= var2; + var2 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2778(graphicsPixels, var0, 0, 0, var3 >> 14, var5 >> 14, var6, var19); + var5 += var15; + var3 += var16; + var6 += var20; + var0 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var0, 0, 0, var3 >> 14, var4 >> 14, var6, var19); + var4 += var17; + var3 += var16; + var6 += var20; + var0 += graphicsPixelsWidth; + } + } + } + } + } + else if (var1 <= var2) + { + if (var1 < Rasterizer3D_clipHeight) + { + if (var2 > Rasterizer3D_clipHeight) + { + var2 = Rasterizer3D_clipHeight; + } + + if (var0 > Rasterizer3D_clipHeight) + { + var0 = Rasterizer3D_clipHeight; + } + + var7 = var19 + ((var7 << 8) - var19 * var4); + if (var2 < var0) + { + var3 = var4 <<= 14; + if (var1 < 0) + { + var3 -= var16 * var1; + var4 -= var15 * var1; + var7 -= var20 * var1; + var1 = 0; + } + + var5 <<= 14; + if (var2 < 0) + { + var5 -= var17 * var2; + var2 = 0; + } + + if (var2 != var1 && var16 < var15 || var2 == var1 && var16 > var17) + { + var0 -= var2; + var2 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2778(graphicsPixels, var1, 0, 0, var3 >> 14, var5 >> 14, var7, var19); + var3 += var16; + var5 += var17; + var7 += var20; + var1 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var1, 0, 0, var3 >> 14, var4 >> 14, var7, var19); + var3 += var16; + var4 += var15; + var7 += var20; + var1 += graphicsPixelsWidth; + } + } + else + { + var0 -= var2; + var2 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2778(graphicsPixels, var1, 0, 0, var5 >> 14, var3 >> 14, var7, var19); + var3 += var16; + var5 += var17; + var7 += var20; + var1 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var1, 0, 0, var4 >> 14, var3 >> 14, var7, var19); + var3 += var16; + var4 += var15; + var7 += var20; + var1 += graphicsPixelsWidth; + } + } + } + else + { + var5 = var4 <<= 14; + if (var1 < 0) + { + var5 -= var16 * var1; + var4 -= var15 * var1; + var7 -= var20 * var1; + var1 = 0; + } + + var3 <<= 14; + if (var0 < 0) + { + var3 -= var0 * var17; + var0 = 0; + } + + if (var16 < var15) + { + var2 -= var0; + var0 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2778(graphicsPixels, var1, 0, 0, var3 >> 14, var4 >> 14, var7, var19); + var3 += var17; + var4 += var15; + var7 += var20; + var1 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var1, 0, 0, var5 >> 14, var4 >> 14, var7, var19); + var5 += var16; + var4 += var15; + var7 += var20; + var1 += graphicsPixelsWidth; + } + } + else + { + var2 -= var0; + var0 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2778(graphicsPixels, var1, 0, 0, var4 >> 14, var3 >> 14, var7, var19); + var3 += var17; + var4 += var15; + var7 += var20; + var1 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var1, 0, 0, var4 >> 14, var5 >> 14, var7, var19); + var5 += var16; + var4 += var15; + var7 += var20; + var1 += graphicsPixelsWidth; + } + } + } + } + } + else if (var2 < Rasterizer3D_clipHeight) + { + if (var0 > Rasterizer3D_clipHeight) + { + var0 = Rasterizer3D_clipHeight; + } + + if (var1 > Rasterizer3D_clipHeight) + { + var1 = Rasterizer3D_clipHeight; + } + + var8 = var19 + ((var8 << 8) - var5 * var19); + if (var0 < var1) + { + var4 = var5 <<= 14; + if (var2 < 0) + { + var4 -= var15 * var2; + var5 -= var17 * var2; + var8 -= var20 * var2; + var2 = 0; + } + + var3 <<= 14; + if (var0 < 0) + { + var3 -= var0 * var16; + var0 = 0; + } + + if (var15 < var17) + { + var1 -= var0; + var0 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2778(graphicsPixels, var2, 0, 0, var4 >> 14, var3 >> 14, var8, var19); + var4 += var15; + var3 += var16; + var8 += var20; + var2 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var2, 0, 0, var4 >> 14, var5 >> 14, var8, var19); + var4 += var15; + var5 += var17; + var8 += var20; + var2 += graphicsPixelsWidth; + } + } + else + { + var1 -= var0; + var0 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2778(graphicsPixels, var2, 0, 0, var3 >> 14, var4 >> 14, var8, var19); + var4 += var15; + var3 += var16; + var8 += var20; + var2 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var2, 0, 0, var5 >> 14, var4 >> 14, var8, var19); + var4 += var15; + var5 += var17; + var8 += var20; + var2 += graphicsPixelsWidth; + } + } + } + else + { + var3 = var5 <<= 14; + if (var2 < 0) + { + var3 -= var15 * var2; + var5 -= var17 * var2; + var8 -= var20 * var2; + var2 = 0; + } + + var4 <<= 14; + if (var1 < 0) + { + var4 -= var16 * var1; + var1 = 0; + } + + if (var15 < var17) + { + var0 -= var1; + var1 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2778(graphicsPixels, var2, 0, 0, var4 >> 14, var5 >> 14, var8, var19); + var4 += var16; + var5 += var17; + var8 += var20; + var2 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var2, 0, 0, var3 >> 14, var5 >> 14, var8, var19); + var3 += var15; + var5 += var17; + var8 += var20; + var2 += graphicsPixelsWidth; + } + } + else + { + var0 -= var1; + var1 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2778(graphicsPixels, var2, 0, 0, var5 >> 14, var4 >> 14, var8, var19); + var4 += var16; + var5 += var17; + var8 += var20; + var2 += graphicsPixelsWidth; + } + } + + method2778(graphicsPixels, var2, 0, 0, var5 >> 14, var3 >> 14, var8, var19); + var3 += var15; + var5 += var17; + var8 += var20; + var2 += graphicsPixelsWidth; + } + } + } + } + } + } + + + final void method2778(int[] var0, int var1, int var2, int var3, int var4, int var5, int var6, int var7) + { + if (rasterClipEnable) + { + if (var5 > rasterClipX) + { + var5 = rasterClipX; + } + + if (var4 < 0) + { + var4 = 0; + } + } + + if (var4 < var5) + { + var1 += var4; + var6 += var4 * var7; + int var8; + int var9; + int var10; + if (rasterGouraudLowRes) + { + var3 = var5 - var4 >> 2; + var7 <<= 2; + if (rasterAlpha == 0) + { + if (var3 > 0) + { + do + { + var2 = colorPalette[var6 >> 8]; + var6 += var7; + var0[var1++] = var2; + var0[var1++] = var2; + var0[var1++] = var2; + var0[var1++] = var2; + --var3; + } while (var3 > 0); + } + + var3 = var5 - var4 & 3; + if (var3 > 0) + { + var2 = colorPalette[var6 >> 8]; + + do + { + var0[var1++] = var2; + --var3; + } while (var3 > 0); + } + } + else + { + var8 = rasterAlpha; + var9 = 256 - rasterAlpha; + if (var3 > 0) + { + do + { + var2 = colorPalette[var6 >> 8]; + var6 += var7; + var2 = (var9 * (var2 & 65280) >> 8 & 65280) + (var9 * (var2 & 16711935) >> 8 & 16711935); + var10 = var0[var1]; + var0[var1++] = ((var10 & 16711935) * var8 >> 8 & 16711935) + var2 + (var8 * (var10 & 65280) >> 8 & 65280); + var10 = var0[var1]; + var0[var1++] = ((var10 & 16711935) * var8 >> 8 & 16711935) + var2 + (var8 * (var10 & 65280) >> 8 & 65280); + var10 = var0[var1]; + var0[var1++] = ((var10 & 16711935) * var8 >> 8 & 16711935) + var2 + (var8 * (var10 & 65280) >> 8 & 65280); + var10 = var0[var1]; + var0[var1++] = ((var10 & 16711935) * var8 >> 8 & 16711935) + var2 + (var8 * (var10 & 65280) >> 8 & 65280); + --var3; + } while (var3 > 0); + } + + var3 = var5 - var4 & 3; + if (var3 > 0) + { + var2 = colorPalette[var6 >> 8]; + var2 = (var9 * (var2 & 65280) >> 8 & 65280) + (var9 * (var2 & 16711935) >> 8 & 16711935); + + do + { + var10 = var0[var1]; + var0[var1++] = ((var10 & 16711935) * var8 >> 8 & 16711935) + var2 + (var8 * (var10 & 65280) >> 8 & 65280); + --var3; + } while (var3 > 0); + } + } + + } + else + { + var3 = var5 - var4; + if (rasterAlpha == 0) + { + do + { + var0[var1++] = colorPalette[var6 >> 8]; + var6 += var7; + --var3; + } while (var3 > 0); + } + else + { + var8 = rasterAlpha; + var9 = 256 - rasterAlpha; + + do + { + var2 = colorPalette[var6 >> 8]; + var6 += var7; + var2 = (var9 * (var2 & 65280) >> 8 & 65280) + (var9 * (var2 & 16711935) >> 8 & 16711935); + var10 = var0[var1]; + var0[var1++] = ((var10 & 16711935) * var8 >> 8 & 16711935) + var2 + (var8 * (var10 & 65280) >> 8 & 65280); + --var3; + } while (var3 > 0); + } + + } + } + } + + + public final void rasterFlat(int var0, int var1, int var2, int var3, int var4, int var5, int var6) + { + int var7 = 0; + if (var0 != var1) + { + var7 = (var4 - var3 << 14) / (var1 - var0); + } + + int var8 = 0; + if (var2 != var1) + { + var8 = (var5 - var4 << 14) / (var2 - var1); + } + + int var9 = 0; + if (var0 != var2) + { + var9 = (var3 - var5 << 14) / (var0 - var2); + } + + if (var0 <= var1 && var0 <= var2) + { + if (var0 < Rasterizer3D_clipHeight) + { + if (var1 > Rasterizer3D_clipHeight) + { + var1 = Rasterizer3D_clipHeight; + } + + if (var2 > Rasterizer3D_clipHeight) + { + var2 = Rasterizer3D_clipHeight; + } + + if (var1 < var2) + { + var5 = var3 <<= 14; + if (var0 < 0) + { + var5 -= var0 * var9; + var3 -= var0 * var7; + var0 = 0; + } + + var4 <<= 14; + if (var1 < 0) + { + var4 -= var8 * var1; + var1 = 0; + } + + if ((var0 == var1 || var9 >= var7) && (var0 != var1 || var9 <= var8)) + { + var2 -= var1; + var1 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2842(graphicsPixels, var0, var6, 0, var4 >> 14, var5 >> 14); + var5 += var9; + var4 += var8; + var0 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var0, var6, 0, var3 >> 14, var5 >> 14); + var5 += var9; + var3 += var7; + var0 += graphicsPixelsWidth; + } + } + else + { + var2 -= var1; + var1 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2842(graphicsPixels, var0, var6, 0, var5 >> 14, var4 >> 14); + var5 += var9; + var4 += var8; + var0 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var0, var6, 0, var5 >> 14, var3 >> 14); + var5 += var9; + var3 += var7; + var0 += graphicsPixelsWidth; + } + } + } + else + { + var4 = var3 <<= 14; + if (var0 < 0) + { + var4 -= var0 * var9; + var3 -= var0 * var7; + var0 = 0; + } + + var5 <<= 14; + if (var2 < 0) + { + var5 -= var8 * var2; + var2 = 0; + } + + if (var0 != var2 && var9 < var7 || var0 == var2 && var8 > var7) + { + var1 -= var2; + var2 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2842(graphicsPixels, var0, var6, 0, var5 >> 14, var3 >> 14); + var5 += var8; + var3 += var7; + var0 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var0, var6, 0, var4 >> 14, var3 >> 14); + var4 += var9; + var3 += var7; + var0 += graphicsPixelsWidth; + } + } + else + { + var1 -= var2; + var2 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2842(graphicsPixels, var0, var6, 0, var3 >> 14, var5 >> 14); + var5 += var8; + var3 += var7; + var0 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var0, var6, 0, var3 >> 14, var4 >> 14); + var4 += var9; + var3 += var7; + var0 += graphicsPixelsWidth; + } + } + } + } + } + else if (var1 <= var2) + { + if (var1 < Rasterizer3D_clipHeight) + { + if (var2 > Rasterizer3D_clipHeight) + { + var2 = Rasterizer3D_clipHeight; + } + + if (var0 > Rasterizer3D_clipHeight) + { + var0 = Rasterizer3D_clipHeight; + } + + if (var2 < var0) + { + var3 = var4 <<= 14; + if (var1 < 0) + { + var3 -= var7 * var1; + var4 -= var8 * var1; + var1 = 0; + } + + var5 <<= 14; + if (var2 < 0) + { + var5 -= var9 * var2; + var2 = 0; + } + + if ((var2 == var1 || var7 >= var8) && (var2 != var1 || var7 <= var9)) + { + var0 -= var2; + var2 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2842(graphicsPixels, var1, var6, 0, var5 >> 14, var3 >> 14); + var3 += var7; + var5 += var9; + var1 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var1, var6, 0, var4 >> 14, var3 >> 14); + var3 += var7; + var4 += var8; + var1 += graphicsPixelsWidth; + } + } + else + { + var0 -= var2; + var2 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2842(graphicsPixels, var1, var6, 0, var3 >> 14, var5 >> 14); + var3 += var7; + var5 += var9; + var1 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var1, var6, 0, var3 >> 14, var4 >> 14); + var3 += var7; + var4 += var8; + var1 += graphicsPixelsWidth; + } + } + } + else + { + var5 = var4 <<= 14; + if (var1 < 0) + { + var5 -= var7 * var1; + var4 -= var8 * var1; + var1 = 0; + } + + var3 <<= 14; + if (var0 < 0) + { + var3 -= var0 * var9; + var0 = 0; + } + + if (var7 < var8) + { + var2 -= var0; + var0 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2842(graphicsPixels, var1, var6, 0, var3 >> 14, var4 >> 14); + var3 += var9; + var4 += var8; + var1 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var1, var6, 0, var5 >> 14, var4 >> 14); + var5 += var7; + var4 += var8; + var1 += graphicsPixelsWidth; + } + } + else + { + var2 -= var0; + var0 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2842(graphicsPixels, var1, var6, 0, var4 >> 14, var3 >> 14); + var3 += var9; + var4 += var8; + var1 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var1, var6, 0, var4 >> 14, var5 >> 14); + var5 += var7; + var4 += var8; + var1 += graphicsPixelsWidth; + } + } + } + } + } + else if (var2 < Rasterizer3D_clipHeight) + { + if (var0 > Rasterizer3D_clipHeight) + { + var0 = Rasterizer3D_clipHeight; + } + + if (var1 > Rasterizer3D_clipHeight) + { + var1 = Rasterizer3D_clipHeight; + } + + if (var0 < var1) + { + var4 = var5 <<= 14; + if (var2 < 0) + { + var4 -= var8 * var2; + var5 -= var9 * var2; + var2 = 0; + } + + var3 <<= 14; + if (var0 < 0) + { + var3 -= var0 * var7; + var0 = 0; + } + + if (var8 < var9) + { + var1 -= var0; + var0 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2842(graphicsPixels, var2, var6, 0, var4 >> 14, var3 >> 14); + var4 += var8; + var3 += var7; + var2 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var2, var6, 0, var4 >> 14, var5 >> 14); + var4 += var8; + var5 += var9; + var2 += graphicsPixelsWidth; + } + } + else + { + var1 -= var0; + var0 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2842(graphicsPixels, var2, var6, 0, var3 >> 14, var4 >> 14); + var4 += var8; + var3 += var7; + var2 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var2, var6, 0, var5 >> 14, var4 >> 14); + var4 += var8; + var5 += var9; + var2 += graphicsPixelsWidth; + } + } + } + else + { + var3 = var5 <<= 14; + if (var2 < 0) + { + var3 -= var8 * var2; + var5 -= var9 * var2; + var2 = 0; + } + + var4 <<= 14; + if (var1 < 0) + { + var4 -= var7 * var1; + var1 = 0; + } + + if (var8 < var9) + { + var0 -= var1; + var1 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2842(graphicsPixels, var2, var6, 0, var4 >> 14, var5 >> 14); + var4 += var7; + var5 += var9; + var2 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var2, var6, 0, var3 >> 14, var5 >> 14); + var3 += var8; + var5 += var9; + var2 += graphicsPixelsWidth; + } + } + else + { + var0 -= var1; + var1 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2842(graphicsPixels, var2, var6, 0, var5 >> 14, var4 >> 14); + var4 += var7; + var5 += var9; + var2 += graphicsPixelsWidth; + } + } + + method2842(graphicsPixels, var2, var6, 0, var5 >> 14, var3 >> 14); + var3 += var8; + var5 += var9; + var2 += graphicsPixelsWidth; + } + } + } + } + } + + + final void method2842(int[] var0, int var1, int var2, int var3, int var4, int var5) + { + if (rasterClipEnable) + { + if (var5 > rasterClipX) + { + var5 = rasterClipX; + } + + if (var4 < 0) + { + var4 = 0; + } + } + + if (var4 < var5) + { + var1 += var4; + var3 = var5 - var4 >> 2; + if (rasterAlpha != 0) + { + if (rasterAlpha == 254) + { + while (true) + { + --var3; + if (var3 < 0) + { + var3 = var5 - var4 & 3; + + while (true) + { + --var3; + if (var3 < 0) + { + return; + } + + var0[var1++] = var0[var1]; + } + } + + var0[var1++] = var0[var1]; + var0[var1++] = var0[var1]; + var0[var1++] = var0[var1]; + var0[var1++] = var0[var1]; + } + } + else + { + int var6 = rasterAlpha; + int var7 = 256 - rasterAlpha; + var2 = (var7 * (var2 & 65280) >> 8 & 65280) + (var7 * (var2 & 16711935) >> 8 & 16711935); + + while (true) + { + --var3; + int var8; + if (var3 < 0) + { + var3 = var5 - var4 & 3; + + while (true) + { + --var3; + if (var3 < 0) + { + return; + } + + var8 = var0[var1]; + var0[var1++] = ((var8 & 16711935) * var6 >> 8 & 16711935) + var2 + (var6 * (var8 & 65280) >> 8 & 65280); + } + } + + var8 = var0[var1]; + var0[var1++] = ((var8 & 16711935) * var6 >> 8 & 16711935) + var2 + (var6 * (var8 & 65280) >> 8 & 65280); + var8 = var0[var1]; + var0[var1++] = ((var8 & 16711935) * var6 >> 8 & 16711935) + var2 + (var6 * (var8 & 65280) >> 8 & 65280); + var8 = var0[var1]; + var0[var1++] = ((var8 & 16711935) * var6 >> 8 & 16711935) + var2 + (var6 * (var8 & 65280) >> 8 & 65280); + var8 = var0[var1]; + var0[var1++] = ((var8 & 16711935) * var6 >> 8 & 16711935) + var2 + (var6 * (var8 & 65280) >> 8 & 65280); + } + } + } + else + { + while (true) + { + --var3; + if (var3 < 0) + { + var3 = var5 - var4 & 3; + + while (true) + { + --var3; + if (var3 < 0) + { + return; + } + + var0[var1++] = var2; + } + } + + var0[var1++] = var2; + var0[var1++] = var2; + var0[var1++] = var2; + var0[var1++] = var2; + } + } + } + } + + + final void rasterTextureAffine(int var0, int var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8, int var9, int var10, int var11, int var12, int var13, int var14, int var15, int var16, int var17, int var18) + { + int[] var19 = textureProvider.load(var18); + int var20; + if (var19 == null) + { + var20 = textureProvider.getAverageTextureRGB(var18); + rasterGouraud(var0, var1, var2, var3, var4, var5, method2794(var20, var6), method2794(var20, var7), method2794(var20, var8)); + } + else + { + lowMem = textureProvider.vmethod3066(var18); + field1909 = textureProvider.vmethod3057(var18); + var20 = var4 - var3; + int var21 = var1 - var0; + int var22 = var5 - var3; + int var23 = var2 - var0; + int var24 = var7 - var6; + int var25 = var8 - var6; + int var26 = 0; + if (var0 != var1) + { + var26 = (var4 - var3 << 14) / (var1 - var0); + } + + int var27 = 0; + if (var2 != var1) + { + var27 = (var5 - var4 << 14) / (var2 - var1); + } + + int var28 = 0; + if (var0 != var2) + { + var28 = (var3 - var5 << 14) / (var0 - var2); + } + + int var29 = var20 * var23 - var22 * var21; + if (var29 != 0) + { + int var30 = (var24 * var23 - var25 * var21 << 9) / var29; + int var31 = (var25 * var20 - var24 * var22 << 9) / var29; + var10 = var9 - var10; + var13 = var12 - var13; + var16 = var15 - var16; + var11 -= var9; + var14 -= var12; + var17 -= var15; + int var32 = var11 * var12 - var9 * var14 << 14; + int var33 = (int) (((long) (var15 * var14 - var17 * var12) << 3 << 14) / (long) Rasterizer3D_zoom); + int var34 = (int) (((long) (var17 * var9 - var11 * var15) << 14) / (long) Rasterizer3D_zoom); + int var35 = var10 * var12 - var13 * var9 << 14; + int var36 = (int) (((long) (var13 * var15 - var16 * var12) << 3 << 14) / (long) Rasterizer3D_zoom); + int var37 = (int) (((long) (var16 * var9 - var10 * var15) << 14) / (long) Rasterizer3D_zoom); + int var38 = var13 * var11 - var10 * var14 << 14; + int var39 = (int) (((long) (var16 * var14 - var13 * var17) << 3 << 14) / (long) Rasterizer3D_zoom); + int var40 = (int) (((long) (var17 * var10 - var11 * var16) << 14) / (long) Rasterizer3D_zoom); + int var41; + if (var0 <= var1 && var0 <= var2) + { + if (var0 < Rasterizer3D_clipHeight) + { + if (var1 > Rasterizer3D_clipHeight) + { + var1 = Rasterizer3D_clipHeight; + } + + if (var2 > Rasterizer3D_clipHeight) + { + var2 = Rasterizer3D_clipHeight; + } + + var6 = var30 + ((var6 << 9) - var3 * var30); + if (var1 < var2) + { + var5 = var3 <<= 14; + if (var0 < 0) + { + var5 -= var0 * var28; + var3 -= var0 * var26; + var6 -= var0 * var31; + var0 = 0; + } + + var4 <<= 14; + if (var1 < 0) + { + var4 -= var27 * var1; + var1 = 0; + } + + var41 = var0 - centerY; + var32 += var34 * var41; + var35 += var37 * var41; + var38 += var40 * var41; + if ((var0 == var1 || var28 >= var26) && (var0 != var1 || var28 <= var27)) + { + var2 -= var1; + var1 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var0, var4 >> 14, var5 >> 14, var6, var30, var32, var35, var38, var33, var36, var39); + var5 += var28; + var4 += var27; + var6 += var31; + var0 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var0, var3 >> 14, var5 >> 14, var6, var30, var32, var35, var38, var33, var36, var39); + var5 += var28; + var3 += var26; + var6 += var31; + var0 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + else + { + var2 -= var1; + var1 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var0, var5 >> 14, var4 >> 14, var6, var30, var32, var35, var38, var33, var36, var39); + var5 += var28; + var4 += var27; + var6 += var31; + var0 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var0, var5 >> 14, var3 >> 14, var6, var30, var32, var35, var38, var33, var36, var39); + var5 += var28; + var3 += var26; + var6 += var31; + var0 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + } + else + { + var4 = var3 <<= 14; + if (var0 < 0) + { + var4 -= var0 * var28; + var3 -= var0 * var26; + var6 -= var0 * var31; + var0 = 0; + } + + var5 <<= 14; + if (var2 < 0) + { + var5 -= var27 * var2; + var2 = 0; + } + + var41 = var0 - centerY; + var32 += var34 * var41; + var35 += var37 * var41; + var38 += var40 * var41; + if (var0 != var2 && var28 < var26 || var0 == var2 && var27 > var26) + { + var1 -= var2; + var2 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var0, var5 >> 14, var3 >> 14, var6, var30, var32, var35, var38, var33, var36, var39); + var5 += var27; + var3 += var26; + var6 += var31; + var0 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var0, var4 >> 14, var3 >> 14, var6, var30, var32, var35, var38, var33, var36, var39); + var4 += var28; + var3 += var26; + var6 += var31; + var0 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + else + { + var1 -= var2; + var2 -= var0; + var0 = rasterClipY[var0]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var0, var3 >> 14, var5 >> 14, var6, var30, var32, var35, var38, var33, var36, var39); + var5 += var27; + var3 += var26; + var6 += var31; + var0 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var0, var3 >> 14, var4 >> 14, var6, var30, var32, var35, var38, var33, var36, var39); + var4 += var28; + var3 += var26; + var6 += var31; + var0 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + } + } + } + else if (var1 <= var2) + { + if (var1 < Rasterizer3D_clipHeight) + { + if (var2 > Rasterizer3D_clipHeight) + { + var2 = Rasterizer3D_clipHeight; + } + + if (var0 > Rasterizer3D_clipHeight) + { + var0 = Rasterizer3D_clipHeight; + } + + var7 = var30 + ((var7 << 9) - var30 * var4); + if (var2 < var0) + { + var3 = var4 <<= 14; + if (var1 < 0) + { + var3 -= var26 * var1; + var4 -= var27 * var1; + var7 -= var31 * var1; + var1 = 0; + } + + var5 <<= 14; + if (var2 < 0) + { + var5 -= var28 * var2; + var2 = 0; + } + + var41 = var1 - centerY; + var32 += var34 * var41; + var35 += var37 * var41; + var38 += var40 * var41; + if ((var2 == var1 || var26 >= var27) && (var2 != var1 || var26 <= var28)) + { + var0 -= var2; + var2 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var1, var5 >> 14, var3 >> 14, var7, var30, var32, var35, var38, var33, var36, var39); + var3 += var26; + var5 += var28; + var7 += var31; + var1 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var1, var4 >> 14, var3 >> 14, var7, var30, var32, var35, var38, var33, var36, var39); + var3 += var26; + var4 += var27; + var7 += var31; + var1 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + else + { + var0 -= var2; + var2 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var2; + if (var2 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var1, var3 >> 14, var5 >> 14, var7, var30, var32, var35, var38, var33, var36, var39); + var3 += var26; + var5 += var28; + var7 += var31; + var1 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var1, var3 >> 14, var4 >> 14, var7, var30, var32, var35, var38, var33, var36, var39); + var3 += var26; + var4 += var27; + var7 += var31; + var1 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + } + else + { + var5 = var4 <<= 14; + if (var1 < 0) + { + var5 -= var26 * var1; + var4 -= var27 * var1; + var7 -= var31 * var1; + var1 = 0; + } + + var3 <<= 14; + if (var0 < 0) + { + var3 -= var0 * var28; + var0 = 0; + } + + var41 = var1 - centerY; + var32 += var34 * var41; + var35 += var37 * var41; + var38 += var40 * var41; + if (var26 < var27) + { + var2 -= var0; + var0 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var1, var3 >> 14, var4 >> 14, var7, var30, var32, var35, var38, var33, var36, var39); + var3 += var28; + var4 += var27; + var7 += var31; + var1 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var1, var5 >> 14, var4 >> 14, var7, var30, var32, var35, var38, var33, var36, var39); + var5 += var26; + var4 += var27; + var7 += var31; + var1 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + else + { + var2 -= var0; + var0 -= var1; + var1 = rasterClipY[var1]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var2; + if (var2 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var1, var4 >> 14, var3 >> 14, var7, var30, var32, var35, var38, var33, var36, var39); + var3 += var28; + var4 += var27; + var7 += var31; + var1 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var1, var4 >> 14, var5 >> 14, var7, var30, var32, var35, var38, var33, var36, var39); + var5 += var26; + var4 += var27; + var7 += var31; + var1 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + } + } + } + else if (var2 < Rasterizer3D_clipHeight) + { + if (var0 > Rasterizer3D_clipHeight) + { + var0 = Rasterizer3D_clipHeight; + } + + if (var1 > Rasterizer3D_clipHeight) + { + var1 = Rasterizer3D_clipHeight; + } + + var8 = (var8 << 9) - var5 * var30 + var30; + if (var0 < var1) + { + var4 = var5 <<= 14; + if (var2 < 0) + { + var4 -= var27 * var2; + var5 -= var28 * var2; + var8 -= var31 * var2; + var2 = 0; + } + + var3 <<= 14; + if (var0 < 0) + { + var3 -= var0 * var26; + var0 = 0; + } + + var41 = var2 - centerY; + var32 += var34 * var41; + var35 += var37 * var41; + var38 += var40 * var41; + if (var27 < var28) + { + var1 -= var0; + var0 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var2, var4 >> 14, var3 >> 14, var8, var30, var32, var35, var38, var33, var36, var39); + var4 += var27; + var3 += var26; + var8 += var31; + var2 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var2, var4 >> 14, var5 >> 14, var8, var30, var32, var35, var38, var33, var36, var39); + var4 += var27; + var5 += var28; + var8 += var31; + var2 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + else + { + var1 -= var0; + var0 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var0; + if (var0 < 0) + { + while (true) + { + --var1; + if (var1 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var2, var3 >> 14, var4 >> 14, var8, var30, var32, var35, var38, var33, var36, var39); + var4 += var27; + var3 += var26; + var8 += var31; + var2 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var2, var5 >> 14, var4 >> 14, var8, var30, var32, var35, var38, var33, var36, var39); + var4 += var27; + var5 += var28; + var8 += var31; + var2 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + } + else + { + var3 = var5 <<= 14; + if (var2 < 0) + { + var3 -= var27 * var2; + var5 -= var28 * var2; + var8 -= var31 * var2; + var2 = 0; + } + + var4 <<= 14; + if (var1 < 0) + { + var4 -= var26 * var1; + var1 = 0; + } + + var41 = var2 - centerY; + var32 += var34 * var41; + var35 += var37 * var41; + var38 += var40 * var41; + if (var27 < var28) + { + var0 -= var1; + var1 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var2, var4 >> 14, var5 >> 14, var8, var30, var32, var35, var38, var33, var36, var39); + var4 += var26; + var5 += var28; + var8 += var31; + var2 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var2, var3 >> 14, var5 >> 14, var8, var30, var32, var35, var38, var33, var36, var39); + var3 += var27; + var5 += var28; + var8 += var31; + var2 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + else + { + var0 -= var1; + var1 -= var2; + var2 = rasterClipY[var2]; + + while (true) + { + --var1; + if (var1 < 0) + { + while (true) + { + --var0; + if (var0 < 0) + { + return; + } + + method2791(graphicsPixels, var19, 0, 0, var2, var5 >> 14, var4 >> 14, var8, var30, var32, var35, var38, var33, var36, var39); + var4 += var26; + var5 += var28; + var8 += var31; + var2 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + + method2791(graphicsPixels, var19, 0, 0, var2, var5 >> 14, var3 >> 14, var8, var30, var32, var35, var38, var33, var36, var39); + var3 += var27; + var5 += var28; + var8 += var31; + var2 += graphicsPixelsWidth; + var32 += var34; + var35 += var37; + var38 += var40; + } + } + } + } + } + } + } + + + final void method2791(int[] var0, int[] var1, int var2, int var3, int var4, int var5, int var6, int var7, int var8, int var9, int var10, int var11, int var12, int var13, int var14) + { + if (rasterClipEnable) + { + if (var6 > rasterClipX) + { + var6 = rasterClipX; + } + + if (var5 < 0) + { + var5 = 0; + } + } + + if (var5 < var6) + { + var4 += var5; + var7 += var5 * var8; + int var17 = var6 - var5; + int var15; + int var16; + int var10000; + int var18; + int var19; + int var20; + int var21; + int var22; + int var23; + if (lowMem) + { + var23 = var5 - centerX; + var9 += var23 * (var12 >> 3); + var10 += (var13 >> 3) * var23; + var11 += var23 * (var14 >> 3); + var22 = var11 >> 12; + if (var22 != 0) + { + var18 = var9 / var22; + var19 = var10 / var22; + if (var18 < 0) + { + var18 = 0; + } + else if (var18 > 4032) + { + var18 = 4032; + } + } + else + { + var18 = 0; + var19 = 0; + } + + var9 += var12; + var10 += var13; + var11 += var14; + var22 = var11 >> 12; + if (var22 != 0) + { + var20 = var9 / var22; + var21 = var10 / var22; + if (var20 < 0) + { + var20 = 0; + } + else if (var20 > 4032) + { + var20 = 4032; + } + } + else + { + var20 = 0; + var21 = 0; + } + + var2 = (var18 << 20) + var19; + var16 = (var21 - var19 >> 3) + (var20 - var18 >> 3 << 20); + var17 >>= 3; + var8 <<= 3; + var15 = var7 >> 8; + if (field1909) + { + if (var17 > 0) + { + do + { + var3 = var1[(var2 >>> 26) + (var2 & 4032)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 >>> 26) + (var2 & 4032)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 >>> 26) + (var2 & 4032)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 >>> 26) + (var2 & 4032)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 >>> 26) + (var2 & 4032)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 >>> 26) + (var2 & 4032)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 >>> 26) + (var2 & 4032)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 >>> 26) + (var2 & 4032)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var10000 = var16 + var2; + var18 = var20; + var19 = var21; + var9 += var12; + var10 += var13; + var11 += var14; + var22 = var11 >> 12; + if (var22 != 0) + { + var20 = var9 / var22; + var21 = var10 / var22; + if (var20 < 0) + { + var20 = 0; + } + else if (var20 > 4032) + { + var20 = 4032; + } + } + else + { + var20 = 0; + var21 = 0; + } + + var2 = (var18 << 20) + var19; + var16 = (var21 - var19 >> 3) + (var20 - var18 >> 3 << 20); + var7 += var8; + var15 = var7 >> 8; + --var17; + } while (var17 > 0); + } + + var17 = var6 - var5 & 7; + if (var17 > 0) + { + do + { + var3 = var1[(var2 >>> 26) + (var2 & 4032)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + --var17; + } while (var17 > 0); + } + } + else + { + if (var17 > 0) + { + do + { + if ((var3 = var1[(var2 >>> 26) + (var2 & 4032)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 >>> 26) + (var2 & 4032)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 >>> 26) + (var2 & 4032)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 >>> 26) + (var2 & 4032)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 >>> 26) + (var2 & 4032)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 >>> 26) + (var2 & 4032)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 >>> 26) + (var2 & 4032)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 >>> 26) + (var2 & 4032)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var10000 = var16 + var2; + var18 = var20; + var19 = var21; + var9 += var12; + var10 += var13; + var11 += var14; + var22 = var11 >> 12; + if (var22 != 0) + { + var20 = var9 / var22; + var21 = var10 / var22; + if (var20 < 0) + { + var20 = 0; + } + else if (var20 > 4032) + { + var20 = 4032; + } + } + else + { + var20 = 0; + var21 = 0; + } + + var2 = (var18 << 20) + var19; + var16 = (var21 - var19 >> 3) + (var20 - var18 >> 3 << 20); + var7 += var8; + var15 = var7 >> 8; + --var17; + } while (var17 > 0); + } + + var17 = var6 - var5 & 7; + if (var17 > 0) + { + do + { + if ((var3 = var1[(var2 >>> 26) + (var2 & 4032)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + --var17; + } while (var17 > 0); + } + } + } + else + { + var23 = var5 - centerX; + var9 += var23 * (var12 >> 3); + var10 += (var13 >> 3) * var23; + var11 += var23 * (var14 >> 3); + var22 = var11 >> 14; + if (var22 != 0) + { + var18 = var9 / var22; + var19 = var10 / var22; + if (var18 < 0) + { + var18 = 0; + } + else if (var18 > 16256) + { + var18 = 16256; + } + } + else + { + var18 = 0; + var19 = 0; + } + + var9 += var12; + var10 += var13; + var11 += var14; + var22 = var11 >> 14; + if (var22 != 0) + { + var20 = var9 / var22; + var21 = var10 / var22; + if (var20 < 0) + { + var20 = 0; + } + else if (var20 > 16256) + { + var20 = 16256; + } + } + else + { + var20 = 0; + var21 = 0; + } + + var2 = (var18 << 18) + var19; + var16 = (var21 - var19 >> 3) + (var20 - var18 >> 3 << 18); + var17 >>= 3; + var8 <<= 3; + var15 = var7 >> 8; + if (field1909) + { + if (var17 > 0) + { + do + { + var3 = var1[(var2 & 16256) + (var2 >>> 25)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 & 16256) + (var2 >>> 25)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 & 16256) + (var2 >>> 25)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 & 16256) + (var2 >>> 25)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 & 16256) + (var2 >>> 25)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 & 16256) + (var2 >>> 25)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 & 16256) + (var2 >>> 25)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + var3 = var1[(var2 & 16256) + (var2 >>> 25)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var10000 = var16 + var2; + var18 = var20; + var19 = var21; + var9 += var12; + var10 += var13; + var11 += var14; + var22 = var11 >> 14; + if (var22 != 0) + { + var20 = var9 / var22; + var21 = var10 / var22; + if (var20 < 0) + { + var20 = 0; + } + else if (var20 > 16256) + { + var20 = 16256; + } + } + else + { + var20 = 0; + var21 = 0; + } + + var2 = (var18 << 18) + var19; + var16 = (var21 - var19 >> 3) + (var20 - var18 >> 3 << 18); + var7 += var8; + var15 = var7 >> 8; + --var17; + } while (var17 > 0); + } + + var17 = var6 - var5 & 7; + if (var17 > 0) + { + do + { + var3 = var1[(var2 & 16256) + (var2 >>> 25)]; + var0[var4++] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + var2 += var16; + --var17; + } while (var17 > 0); + } + } + else + { + if (var17 > 0) + { + do + { + if ((var3 = var1[(var2 & 16256) + (var2 >>> 25)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 & 16256) + (var2 >>> 25)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 & 16256) + (var2 >>> 25)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 & 16256) + (var2 >>> 25)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 & 16256) + (var2 >>> 25)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 & 16256) + (var2 >>> 25)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 & 16256) + (var2 >>> 25)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + if ((var3 = var1[(var2 & 16256) + (var2 >>> 25)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var10000 = var16 + var2; + var18 = var20; + var19 = var21; + var9 += var12; + var10 += var13; + var11 += var14; + var22 = var11 >> 14; + if (var22 != 0) + { + var20 = var9 / var22; + var21 = var10 / var22; + if (var20 < 0) + { + var20 = 0; + } + else if (var20 > 16256) + { + var20 = 16256; + } + } + else + { + var20 = 0; + var21 = 0; + } + + var2 = (var18 << 18) + var19; + var16 = (var21 - var19 >> 3) + (var20 - var18 >> 3 << 18); + var7 += var8; + var15 = var7 >> 8; + --var17; + } while (var17 > 0); + } + + var17 = var6 - var5 & 7; + if (var17 > 0) + { + do + { + if ((var3 = var1[(var2 & 16256) + (var2 >>> 25)]) != 0) + { + var0[var4] = (var15 * (var3 & 65280) & 16711680) + ((var3 & 16711935) * var15 & -16711936) >> 8; + } + + ++var4; + var2 += var16; + --var17; + } while (var17 > 0); + } + } + } + + } + } + + static final int method2794(int var0, int var1) + { + var1 = (var0 & 127) * var1 >> 7; + if (var1 < 2) + { + var1 = 2; + } + else if (var1 > 126) + { + var1 = 126; + } + + return (var0 & 65408) + var1; + } +} diff --git a/src/main/java/net/runelite/cache/item/ItemSpriteFactory.java b/src/main/java/net/runelite/cache/item/ItemSpriteFactory.java new file mode 100644 index 0000000..dc89225 --- /dev/null +++ b/src/main/java/net/runelite/cache/item/ItemSpriteFactory.java @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.item; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import net.runelite.cache.definitions.ItemDefinition; +import net.runelite.cache.definitions.ModelDefinition; +import net.runelite.cache.definitions.providers.ItemProvider; +import net.runelite.cache.definitions.providers.ModelProvider; +import net.runelite.cache.definitions.providers.SpriteProvider; +import net.runelite.cache.definitions.providers.TextureProvider; +import net.runelite.cache.models.FaceNormal; +import net.runelite.cache.models.VertexNormal; + +public class ItemSpriteFactory +{ + public static final BufferedImage createSprite(ItemProvider itemProvider, ModelProvider modelProvider, + SpriteProvider spriteProvider, TextureProvider textureProvider, + int itemId, int quantity, int border, int shadowColor, + boolean noted) throws IOException + { + Sprite spritePixels = createSpritePixels(itemProvider, modelProvider, spriteProvider, textureProvider, + itemId, quantity, border, shadowColor, noted); + return spritePixels == null ? null : spritePixels.toBufferedImage(); + } + + private static final Sprite createSpritePixels(ItemProvider itemProvider, ModelProvider modelProvider, + SpriteProvider spriteProvider, TextureProvider textureProvider, + int itemId, int quantity, int border, int shadowColor, + boolean noted) throws IOException + { + ItemDefinition item = itemProvider.provide(itemId); + + if (quantity > 1 && item.countObj != null) + { + int stackItemID = -1; + + for (int i = 0; i < 10; ++i) + { + if (quantity >= item.countCo[i] && item.countCo[i] != 0) + { + stackItemID = item.countObj[i]; + } + } + + if (stackItemID != -1) + { + item = itemProvider.provide(stackItemID); + } + } + + if (item.notedTemplate != -1) + { + item.updateNote(itemProvider.provide(item.notedTemplate), itemProvider.provide(item.notedID)); + } + + Model itemModel = getModel(modelProvider, item); + if (itemModel == null) + { + return null; + } + + Sprite auxSpritePixels = null; + if (item.notedTemplate != -1) + { + auxSpritePixels = createSpritePixels(itemProvider, modelProvider, spriteProvider, textureProvider, + item.notedID, 10, 1, 0, true); + if (auxSpritePixels == null) + { + return null; + } + } + else if (item.boughtTemplateId != -1) + { + auxSpritePixels = createSpritePixels(itemProvider, modelProvider, spriteProvider, textureProvider, + item.boughtId, quantity, border, shadowColor, false); + if (auxSpritePixels == null) + { + return null; + } + } + else if (item.placeholderTemplateId != -1) + { + auxSpritePixels = createSpritePixels(itemProvider, modelProvider, spriteProvider, textureProvider, + item.placeholderId, quantity, 0, 0, false); + if (auxSpritePixels == null) + { + return null; + } + } + + RSTextureProvider rsTextureProvider = new RSTextureProvider(textureProvider, spriteProvider); + + Sprite spritePixels = new Sprite(36, 32); + Graphics3D graphics = new Graphics3D(rsTextureProvider); + graphics.setBrightness(0.6d); + graphics.setRasterBuffer(spritePixels.pixels, 36, 32); + graphics.reset(); + graphics.setRasterClipping(); + graphics.setOffset(16, 16); + graphics.rasterGouraudLowRes = false; + if (item.placeholderTemplateId != -1) + { + auxSpritePixels.drawAtOn(graphics, 0, 0); + } + + int zoom2d = item.zoom2d; + if (noted) + { + zoom2d = (int) ((double) zoom2d * 1.5D); + } + else if (border == 2) + { + zoom2d = (int) ((double) zoom2d * 1.04D); + } + + int var17 = zoom2d * Graphics3D.SINE[item.xan2d] >> 16; + int var18 = zoom2d * Graphics3D.COSINE[item.xan2d] >> 16; + + itemModel.calculateBoundsCylinder(); + itemModel.rotateAndProject(graphics, 0, + item.yan2d, + item.zan2d, + item.xan2d, + item.xOffset2d, + itemModel.modelHeight / 2 + var17 + item.yOffset2d, + var18 + item.yOffset2d); + if (item.boughtTemplateId != -1) + { + auxSpritePixels.drawAtOn(graphics, 0, 0); + } + + if (border >= 1) + { + spritePixels.drawBorder(1); + } + + if (border >= 2) + { + spritePixels.drawBorder(0xffffff); + } + + if (shadowColor != 0) + { + spritePixels.drawShadow(shadowColor); + } + + graphics.setRasterBuffer(spritePixels.pixels, 36, 32); + if (item.notedTemplate != -1) + { + auxSpritePixels.drawAtOn(graphics, 0, 0); + } + + graphics.setRasterBuffer(graphics.graphicsPixels, + graphics.graphicsPixelsWidth, + graphics.graphicsPixelsHeight); + + graphics.setRasterClipping(); + graphics.rasterGouraudLowRes = true; + return spritePixels; + } + + private static Model getModel(ModelProvider modelProvider, ItemDefinition item) throws IOException + { + Model itemModel; + ModelDefinition inventoryModel = modelProvider.provide(item.inventoryModel); + if (inventoryModel == null) + { + return null; + } + + if (item.resizeX != 128 || item.resizeY != 128 || item.resizeZ != 128) + { + inventoryModel.resize(item.resizeX, item.resizeY, item.resizeZ); + } + + if (item.colorFind != null) + { + for (int i = 0; i < item.colorFind.length; ++i) + { + inventoryModel.recolor(item.colorFind[i], item.colorReplace[i]); + } + } + + if (item.textureFind != null) + { + for (int i = 0; i < item.textureFind.length; ++i) + { + inventoryModel.retexture(item.textureFind[i], item.textureReplace[i]); + } + } + + itemModel = light(inventoryModel, item.ambient + 64, item.contrast + 768, -50, -10, -50); + itemModel.isItemModel = true; + return itemModel; + } + + private static Model light(ModelDefinition def, int ambient, int contrast, int x, int y, int z) + { + def.computeNormals(); + int somethingMagnitude = (int) Math.sqrt((double) (z * z + x * x + y * y)); + int var7 = somethingMagnitude * contrast >> 8; + Model litModel = new Model(); + litModel.field1856 = new int[def.faceCount]; + litModel.field1854 = new int[def.faceCount]; + litModel.field1823 = new int[def.faceCount]; + if (def.textureTriangleCount > 0 && def.textureCoordinates != null) + { + int[] var9 = new int[def.textureTriangleCount]; + + int var10; + for (var10 = 0; var10 < def.faceCount; ++var10) + { + if (def.textureCoordinates[var10] != -1) + { + ++var9[def.textureCoordinates[var10] & 255]; + } + } + + litModel.field1852 = 0; + + for (var10 = 0; var10 < def.textureTriangleCount; ++var10) + { + if (var9[var10] > 0 && def.textureRenderTypes[var10] == 0) + { + ++litModel.field1852; + } + } + + litModel.field1844 = new int[litModel.field1852]; + litModel.field1865 = new int[litModel.field1852]; + litModel.field1846 = new int[litModel.field1852]; + var10 = 0; + + + for (int i = 0; i < def.textureTriangleCount; ++i) + { + if (var9[i] > 0 && def.textureRenderTypes[i] == 0) + { + litModel.field1844[var10] = def.textureTriangleVertexIndices1[i] & '\uffff'; + litModel.field1865[var10] = def.textureTriangleVertexIndices2[i] & '\uffff'; + litModel.field1846[var10] = def.textureTriangleVertexIndices3[i] & '\uffff'; + var9[i] = var10++; + } + else + { + var9[i] = -1; + } + } + + litModel.field1840 = new byte[def.faceCount]; + + for (int i = 0; i < def.faceCount; ++i) + { + if (def.textureCoordinates[i] != -1) + { + litModel.field1840[i] = (byte) var9[def.textureCoordinates[i] & 255]; + } + else + { + litModel.field1840[i] = -1; + } + } + } + + for (int faceIdx = 0; faceIdx < def.faceCount; ++faceIdx) + { + byte faceType; + if (def.faceRenderTypes == null) + { + faceType = 0; + } + else + { + faceType = def.faceRenderTypes[faceIdx]; + } + + byte faceAlpha; + if (def.faceAlphas == null) + { + faceAlpha = 0; + } + else + { + faceAlpha = def.faceAlphas[faceIdx]; + } + + short faceTexture; + if (def.faceTextures == null) + { + faceTexture = -1; + } + else + { + faceTexture = def.faceTextures[faceIdx]; + } + + if (faceAlpha == -2) + { + faceType = 3; + } + + if (faceAlpha == -1) + { + faceType = 2; + } + + VertexNormal vertexNormal; + int tmp; + FaceNormal faceNormal; + if (faceTexture == -1) + { + if (faceType != 0) + { + if (faceType == 1) + { + faceNormal = def.faceNormals[faceIdx]; + tmp = (y * faceNormal.y + z * faceNormal.z + x * faceNormal.x) / (var7 / 2 + var7) + ambient; + litModel.field1856[faceIdx] = method2608(def.faceColors[faceIdx] & '\uffff', tmp); + litModel.field1823[faceIdx] = -1; + } + else if (faceType == 3) + { + litModel.field1856[faceIdx] = 128; + litModel.field1823[faceIdx] = -1; + } + else + { + litModel.field1823[faceIdx] = -2; + } + } + else + { + int var15 = def.faceColors[faceIdx] & '\uffff'; + vertexNormal = def.vertexNormals[def.faceVertexIndices1[faceIdx]]; + + tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient; + litModel.field1856[faceIdx] = method2608(var15, tmp); + vertexNormal = def.vertexNormals[def.faceVertexIndices2[faceIdx]]; + + tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient; + litModel.field1854[faceIdx] = method2608(var15, tmp); + vertexNormal = def.vertexNormals[def.faceVertexIndices3[faceIdx]]; + + tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient; + litModel.field1823[faceIdx] = method2608(var15, tmp); + } + } + else if (faceType != 0) + { + if (faceType == 1) + { + faceNormal = def.faceNormals[faceIdx]; + tmp = (y * faceNormal.y + z * faceNormal.z + x * faceNormal.x) / (var7 / 2 + var7) + ambient; + litModel.field1856[faceIdx] = bound2to126(tmp); + litModel.field1823[faceIdx] = -1; + } + else + { + litModel.field1823[faceIdx] = -2; + } + } + else + { + vertexNormal = def.vertexNormals[def.faceVertexIndices1[faceIdx]]; + + tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient; + litModel.field1856[faceIdx] = bound2to126(tmp); + vertexNormal = def.vertexNormals[def.faceVertexIndices2[faceIdx]]; + + tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient; + litModel.field1854[faceIdx] = bound2to126(tmp); + vertexNormal = def.vertexNormals[def.faceVertexIndices3[faceIdx]]; + + tmp = (y * vertexNormal.y + z * vertexNormal.z + x * vertexNormal.x) / (var7 * vertexNormal.magnitude) + ambient; + litModel.field1823[faceIdx] = bound2to126(tmp); + } + } + + litModel.verticesCount = def.vertexCount; + litModel.verticesX = def.vertexPositionsX; + litModel.verticesY = def.vertexPositionsY; + litModel.verticesZ = def.vertexPositionsZ; + litModel.indicesCount = def.faceCount; + litModel.indices1 = def.faceVertexIndices1; + litModel.indices2 = def.faceVertexIndices2; + litModel.indices3 = def.faceVertexIndices3; + litModel.field1838 = def.faceRenderPriorities; + litModel.field1882 = def.faceAlphas; + litModel.field1842 = def.priority; + litModel.field1841 = def.faceTextures; + return litModel; + } + + static final int method2608(int var0, int var1) + { + var1 = ((var0 & 127) * var1) >> 7; + var1 = bound2to126(var1); + + return (var0 & 65408) + var1; + } + + static final int bound2to126(int var0) + { + if (var0 < 2) + { + var0 = 2; + } + else if (var0 > 126) + { + var0 = 126; + } + + return var0; + } +} diff --git a/src/main/java/net/runelite/cache/item/Model.java b/src/main/java/net/runelite/cache/item/Model.java new file mode 100644 index 0000000..e35943a --- /dev/null +++ b/src/main/java/net/runelite/cache/item/Model.java @@ -0,0 +1,773 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.item; + +class Model extends Renderable +{ + boolean[] field1887 = new boolean[4700]; + boolean[] field1885 = new boolean[4700]; + int[] modelViewportYs = new int[4700]; + int[] modelViewportXs = new int[4700]; + int[] modelViewportZs = new int[4700]; + int[] yViewportBuffer = new int[4700]; + int[] field1839 = new int[4700]; + int[] field1869 = new int[4700]; + int[] field1871 = new int[1600]; + int[][] field1868 = new int[1600][512]; + int[] field1872 = new int[12]; + int[][] field1874 = new int[12][2000]; + int[] field1857 = new int[2000]; + int[] field1863 = new int[2000]; + int[] field1877 = new int[12]; + int[] field1831 = new int[10]; + int[] field1837 = new int[10]; + int[] xViewportBuffer = new int[10]; + static int[] Model_sine; + static int[] Model_cosine; + static int[] field1890; + int verticesCount; + int[] verticesX; + int[] verticesY; + int[] verticesZ; + int indicesCount; + int[] indices1; + int[] indices2; + int[] indices3; + int[] field1856; + int[] field1854; + int[] field1823; + byte[] field1838; + byte[] field1882; + byte[] field1840; + short[] field1841; + byte field1842; + int field1852; + int[] field1844; + int[] field1865; + int[] field1846; + public boolean isItemModel; + int boundsType; + int bottomY; + int XYZMag; + int diameter; + int radius; + public int extremeX; + public int extremeY; + public int extremeZ; + + static + { + Model_sine = Graphics3D.SINE; + Model_cosine = Graphics3D.COSINE; + field1890 = Graphics3D.field1933; + } + + Model() + { + this.verticesCount = 0; + this.indicesCount = 0; + this.field1842 = 0; + this.field1852 = 0; + this.isItemModel = false; + this.extremeX = -1; + this.extremeY = -1; + this.extremeZ = -1; + } + + public void calculateBoundsCylinder() + { + if (this.boundsType != 1) + { + this.boundsType = 1; + super.modelHeight = 0; + this.bottomY = 0; + this.XYZMag = 0; + + for (int var1 = 0; var1 < this.verticesCount; ++var1) + { + int var2 = this.verticesX[var1]; + int var3 = this.verticesY[var1]; + int var4 = this.verticesZ[var1]; + if (-var3 > super.modelHeight) + { + super.modelHeight = -var3; + } + + if (var3 > this.bottomY) + { + this.bottomY = var3; + } + + int var5 = var2 * var2 + var4 * var4; + if (var5 > this.XYZMag) + { + this.XYZMag = var5; + } + } + + this.XYZMag = (int) (Math.sqrt((double) this.XYZMag) + 0.99D); + this.radius = (int) (Math.sqrt((double) (this.XYZMag * this.XYZMag + super.modelHeight * super.modelHeight)) + 0.99D); + this.diameter = this.radius + (int) (Math.sqrt((double) (this.XYZMag * this.XYZMag + this.bottomY * this.bottomY)) + 0.99D); + } + } + + public final void rotateAndProject(Graphics3D graphics, int rotation_1, int yRotation, int zRotation, int xRotation, int xOffset, int yOffset, int zOffset) + { + field1871[0] = -1; + // (re?)Calculate magnitude as necessary + if (this.boundsType != 2 && this.boundsType != 1) + { + this.boundsType = 2; + this.XYZMag = 0; + + for (int var1 = 0; var1 < this.verticesCount; ++var1) + { + int x = this.verticesX[var1]; + int y = this.verticesY[var1]; + int z = this.verticesZ[var1]; + int magnitude_squared = x * x + z * z + y * y; + if (magnitude_squared > this.XYZMag) + { + this.XYZMag = magnitude_squared; + } + } + + this.XYZMag = (int) (Math.sqrt((double) this.XYZMag) + 0.99D); + this.radius = this.XYZMag; + this.diameter = this.XYZMag + this.XYZMag; + } + + // rotate + perspective transform + int sinX = Model_sine[xRotation]; + int cosX = Model_cosine[xRotation]; + int zRelatedVariable = sinX * yOffset + cosX * zOffset >> 16; + + for (int i = 0; i < this.verticesCount; ++i) + { + int x = this.verticesX[i]; + int y = this.verticesY[i]; + int z = this.verticesZ[i]; + if (zRotation != 0) + { + int sinZ = Model_sine[zRotation]; + int cosZ = Model_cosine[zRotation]; + int tmp; + tmp = y * sinZ + x * cosZ >> 16; + y = y * cosZ - x * sinZ >> 16; + x = tmp; + } + + if (rotation_1 != 0) + { + int sinR1 = Model_sine[rotation_1]; + int cosR1 = Model_cosine[rotation_1]; + int tmp; + tmp = y * cosR1 - z * sinR1 >> 16; + z = y * sinR1 + z * cosR1 >> 16; + y = tmp; + } + + if (yRotation != 0) + { + int sinY = Model_sine[yRotation]; + int cosY = Model_cosine[yRotation]; + int tmp; + tmp = z * sinY + x * cosY >> 16; + z = z * cosY - x * sinY >> 16; + x = tmp; + } + + x += xOffset; + y += yOffset; + z += zOffset; + int tmp = y * cosX - z * sinX >> 16; + z = y * sinX + z * cosX >> 16; + modelViewportZs[i] = z - zRelatedVariable; + modelViewportYs[i] = x * graphics.Rasterizer3D_zoom / z + graphics.centerX; + modelViewportXs[i] = tmp * graphics.Rasterizer3D_zoom / z + graphics.centerY; + if (this.field1852 > 0) + { + yViewportBuffer[i] = x; + field1839[i] = tmp; + field1869[i] = z; + } + } + + this.method0(graphics, false, false, 0); + } + + + private void method0(Graphics3D graphics, boolean var1, boolean var3, int var4) + { + if (this.diameter < 1600) + { + for (int var5 = 0; var5 < this.diameter; ++var5) + { + field1871[var5] = 0; + } + + int var7; + int var9; + int var10; + int var11; + int var12; + int var13; + int var14; + int var15; + int var16; + int var17; + int var18; + int var19; + int var20; + int var27; + + int var26; + for (var26 = 0; var26 < this.indicesCount; ++var26) + { + if (this.field1823[var26] != -2) + { + var7 = this.indices1[var26]; + var27 = this.indices2[var26]; + var9 = this.indices3[var26]; + var10 = modelViewportYs[var7]; + var11 = modelViewportYs[var27]; + var12 = modelViewportYs[var9]; + if (var1 && (var10 == -5000 || var11 == -5000 || var12 == -5000)) + { + var13 = yViewportBuffer[var7]; + var14 = yViewportBuffer[var27]; + var15 = yViewportBuffer[var9]; + var16 = field1839[var7]; + var17 = field1839[var27]; + var18 = field1839[var9]; + var19 = field1869[var7]; + var20 = field1869[var27]; + int var21 = field1869[var9]; + var13 -= var14; + var15 -= var14; + var16 -= var17; + var18 -= var17; + var19 -= var20; + var21 -= var20; + int var22 = var16 * var21 - var19 * var18; + int var23 = var19 * var15 - var13 * var21; + int var24 = var13 * var18 - var16 * var15; + if (var14 * var22 + var17 * var23 + var20 * var24 > 0) + { + field1885[var26] = true; + int var25 = (modelViewportZs[var7] + modelViewportZs[var27] + modelViewportZs[var9]) / 3 + this.radius; + field1868[var25][field1871[var25]++] = var26; + } + } + else + { + if ((var10 - var11) * (modelViewportXs[var9] - modelViewportXs[var27]) - (var12 - var11) * (modelViewportXs[var7] - modelViewportXs[var27]) > 0) + { + field1885[var26] = false; + if (var10 >= 0 && var11 >= 0 && var12 >= 0 && var10 <= graphics.rasterClipX && var11 <= graphics.rasterClipX && var12 <= graphics.rasterClipX) + { + field1887[var26] = false; + } + else + { + field1887[var26] = true; + } + + var13 = (modelViewportZs[var7] + modelViewportZs[var27] + modelViewportZs[var9]) / 3 + this.radius; + field1868[var13][field1871[var13]++] = var26; + } + } + } + } + + int[] var8; + if (this.field1838 == null) + { + for (var26 = this.diameter - 1; var26 >= 0; --var26) + { + var7 = field1871[var26]; + if (var7 > 0) + { + var8 = field1868[var26]; + + for (var9 = 0; var9 < var7; ++var9) + { + this.method2706(graphics, var8[var9]); + } + } + } + + } + else + { + for (var26 = 0; var26 < 12; ++var26) + { + field1872[var26] = 0; + field1877[var26] = 0; + } + + for (var26 = this.diameter - 1; var26 >= 0; --var26) + { + var7 = field1871[var26]; + if (var7 > 0) + { + var8 = field1868[var26]; + + for (var9 = 0; var9 < var7; ++var9) + { + var10 = var8[var9]; + byte var31 = this.field1838[var10]; + var12 = field1872[var31]++; + field1874[var31][var12] = var10; + if (var31 < 10) + { + field1877[var31] += var26; + } + else if (var31 == 10) + { + field1857[var12] = var26; + } + else + { + field1863[var12] = var26; + } + } + } + } + + var26 = 0; + if (field1872[1] > 0 || field1872[2] > 0) + { + var26 = (field1877[1] + field1877[2]) / (field1872[1] + field1872[2]); + } + + var7 = 0; + if (field1872[3] > 0 || field1872[4] > 0) + { + var7 = (field1877[3] + field1877[4]) / (field1872[3] + field1872[4]); + } + + var27 = 0; + if (field1872[6] > 0 || field1872[8] > 0) + { + var27 = (field1877[8] + field1877[6]) / (field1872[8] + field1872[6]); + } + + var10 = 0; + var11 = field1872[10]; + int[] var28 = field1874[10]; + int[] var29 = field1857; + if (var10 == var11) + { + var10 = 0; + var11 = field1872[11]; + var28 = field1874[11]; + var29 = field1863; + } + + if (var10 < var11) + { + var9 = var29[var10]; + } + else + { + var9 = -1000; + } + + for (var14 = 0; var14 < 10; ++var14) + { + while (var14 == 0 && var9 > var26) + { + this.method2706(graphics, var28[var10++]); + if (var10 == var11 && var28 != field1874[11]) + { + var10 = 0; + var11 = field1872[11]; + var28 = field1874[11]; + var29 = field1863; + } + + if (var10 < var11) + { + var9 = var29[var10]; + } + else + { + var9 = -1000; + } + } + + while (var14 == 3 && var9 > var7) + { + this.method2706(graphics, var28[var10++]); + if (var10 == var11 && var28 != field1874[11]) + { + var10 = 0; + var11 = field1872[11]; + var28 = field1874[11]; + var29 = field1863; + } + + if (var10 < var11) + { + var9 = var29[var10]; + } + else + { + var9 = -1000; + } + } + + while (var14 == 5 && var9 > var27) + { + this.method2706(graphics, var28[var10++]); + if (var10 == var11 && var28 != field1874[11]) + { + var10 = 0; + var11 = field1872[11]; + var28 = field1874[11]; + var29 = field1863; + } + + if (var10 < var11) + { + var9 = var29[var10]; + } + else + { + var9 = -1000; + } + } + + var15 = field1872[var14]; + int[] var30 = field1874[var14]; + + for (var17 = 0; var17 < var15; ++var17) + { + this.method2706(graphics, var30[var17]); + } + } + + while (var9 != -1000) + { + this.method2706(graphics, var28[var10++]); + if (var10 == var11 && var28 != field1874[11]) + { + var10 = 0; + var28 = field1874[11]; + var11 = field1872[11]; + var29 = field1863; + } + + if (var10 < var11) + { + var9 = var29[var10]; + } + else + { + var9 = -1000; + } + } + + } + } + } + + private void method2706(Graphics3D graphics, int var1) + { + if (field1885[var1]) + { + this.method2707(graphics, var1); + } + else + { + int var2 = this.indices1[var1]; + int var3 = this.indices2[var1]; + int var4 = this.indices3[var1]; + graphics.rasterClipEnable = field1887[var1]; + if (this.field1882 == null) + { + graphics.rasterAlpha = 0; + } + else + { + graphics.rasterAlpha = this.field1882[var1] & 255; + } + + if (this.field1841 != null && this.field1841[var1] != -1) + { + int var5; + int var6; + int var7; + if (this.field1840 != null && this.field1840[var1] != -1) + { + int var8 = this.field1840[var1] & 255; + var5 = this.field1844[var8]; + var6 = this.field1865[var8]; + var7 = this.field1846[var8]; + } + else + { + var5 = var2; + var6 = var3; + var7 = var4; + } + + if (this.field1823[var1] == -1) + { + graphics.rasterTextureAffine(modelViewportXs[var2], modelViewportXs[var3], modelViewportXs[var4], modelViewportYs[var2], modelViewportYs[var3], modelViewportYs[var4], this.field1856[var1], this.field1856[var1], this.field1856[var1], yViewportBuffer[var5], yViewportBuffer[var6], yViewportBuffer[var7], field1839[var5], field1839[var6], field1839[var7], field1869[var5], field1869[var6], field1869[var7], this.field1841[var1]); + } + else + { + graphics.rasterTextureAffine(modelViewportXs[var2], modelViewportXs[var3], modelViewportXs[var4], modelViewportYs[var2], modelViewportYs[var3], modelViewportYs[var4], this.field1856[var1], this.field1854[var1], this.field1823[var1], yViewportBuffer[var5], yViewportBuffer[var6], yViewportBuffer[var7], field1839[var5], field1839[var6], field1839[var7], field1869[var5], field1869[var6], field1869[var7], this.field1841[var1]); + } + } + else if (this.field1823[var1] == -1) + { + int[] field1889 = graphics.colorPalette; + graphics.rasterFlat(modelViewportXs[var2], modelViewportXs[var3], modelViewportXs[var4], modelViewportYs[var2], modelViewportYs[var3], modelViewportYs[var4], field1889[this.field1856[var1]]); + } + else + { + graphics.rasterGouraud(modelViewportXs[var2], modelViewportXs[var3], modelViewportXs[var4], modelViewportYs[var2], modelViewportYs[var3], modelViewportYs[var4], this.field1856[var1], this.field1854[var1], this.field1823[var1]); + } + + } + } + + + private void method2707(Graphics3D graphics, int var1) + { + int var2 = graphics.centerX; + int var3 = graphics.centerY; + int var4 = 0; + int var5 = this.indices1[var1]; + int var6 = this.indices2[var1]; + int var7 = this.indices3[var1]; + int var8 = field1869[var5]; + int var9 = field1869[var6]; + int var10 = field1869[var7]; + if (this.field1882 == null) + { + graphics.rasterAlpha = 0; + } + else + { + graphics.rasterAlpha = this.field1882[var1] & 255; + } + + int var11; + int var12; + int var13; + int var14; + if (var8 >= 50) + { + field1831[var4] = modelViewportYs[var5]; + field1837[var4] = modelViewportXs[var5]; + xViewportBuffer[var4++] = this.field1856[var1]; + } + else + { + var11 = yViewportBuffer[var5]; + var12 = field1839[var5]; + var13 = this.field1856[var1]; + if (var10 >= 50) + { + var14 = field1890[var10 - var8] * (50 - var8); + field1831[var4] = var2 + graphics.Rasterizer3D_zoom * (var11 + ((yViewportBuffer[var7] - var11) * var14 >> 16)) / 50; + field1837[var4] = var3 + graphics.Rasterizer3D_zoom * (var12 + ((field1839[var7] - var12) * var14 >> 16)) / 50; + xViewportBuffer[var4++] = var13 + ((this.field1823[var1] - var13) * var14 >> 16); + } + + if (var9 >= 50) + { + var14 = field1890[var9 - var8] * (50 - var8); + field1831[var4] = var2 + graphics.Rasterizer3D_zoom * (var11 + ((yViewportBuffer[var6] - var11) * var14 >> 16)) / 50; + field1837[var4] = var3 + graphics.Rasterizer3D_zoom * (var12 + ((field1839[var6] - var12) * var14 >> 16)) / 50; + xViewportBuffer[var4++] = var13 + ((this.field1854[var1] - var13) * var14 >> 16); + } + } + + if (var9 >= 50) + { + field1831[var4] = modelViewportYs[var6]; + field1837[var4] = modelViewportXs[var6]; + xViewportBuffer[var4++] = this.field1854[var1]; + } + else + { + var11 = yViewportBuffer[var6]; + var12 = field1839[var6]; + var13 = this.field1854[var1]; + if (var8 >= 50) + { + var14 = field1890[var8 - var9] * (50 - var9); + field1831[var4] = var2 + graphics.Rasterizer3D_zoom * (var11 + ((yViewportBuffer[var5] - var11) * var14 >> 16)) / 50; + field1837[var4] = var3 + graphics.Rasterizer3D_zoom * (var12 + ((field1839[var5] - var12) * var14 >> 16)) / 50; + xViewportBuffer[var4++] = var13 + ((this.field1856[var1] - var13) * var14 >> 16); + } + + if (var10 >= 50) + { + var14 = field1890[var10 - var9] * (50 - var9); + field1831[var4] = var2 + graphics.Rasterizer3D_zoom * (var11 + ((yViewportBuffer[var7] - var11) * var14 >> 16)) / 50; + field1837[var4] = var3 + graphics.Rasterizer3D_zoom * (var12 + ((field1839[var7] - var12) * var14 >> 16)) / 50; + xViewportBuffer[var4++] = var13 + ((this.field1823[var1] - var13) * var14 >> 16); + } + } + + if (var10 >= 50) + { + field1831[var4] = modelViewportYs[var7]; + field1837[var4] = modelViewportXs[var7]; + xViewportBuffer[var4++] = this.field1823[var1]; + } + else + { + var11 = yViewportBuffer[var7]; + var12 = field1839[var7]; + var13 = this.field1823[var1]; + if (var9 >= 50) + { + var14 = field1890[var9 - var10] * (50 - var10); + field1831[var4] = var2 + graphics.Rasterizer3D_zoom * (var11 + ((yViewportBuffer[var6] - var11) * var14 >> 16)) / 50; + field1837[var4] = var3 + graphics.Rasterizer3D_zoom * (var12 + ((field1839[var6] - var12) * var14 >> 16)) / 50; + xViewportBuffer[var4++] = var13 + ((this.field1854[var1] - var13) * var14 >> 16); + } + + if (var8 >= 50) + { + var14 = field1890[var8 - var10] * (50 - var10); + field1831[var4] = var2 + graphics.Rasterizer3D_zoom * (var11 + ((yViewportBuffer[var5] - var11) * var14 >> 16)) / 50; + field1837[var4] = var3 + graphics.Rasterizer3D_zoom * (var12 + ((field1839[var5] - var12) * var14 >> 16)) / 50; + xViewportBuffer[var4++] = var13 + ((this.field1856[var1] - var13) * var14 >> 16); + } + } + + var11 = field1831[0]; + var12 = field1831[1]; + var13 = field1831[2]; + var14 = field1837[0]; + int var15 = field1837[1]; + int var16 = field1837[2]; + graphics.rasterClipEnable = false; + int var17; + int var18; + int var19; + int var20; + if (var4 == 3) + { + if (var11 < 0 || var12 < 0 || var13 < 0 || var11 > graphics.rasterClipX || var12 > graphics.rasterClipX || var13 > graphics.rasterClipX) + { + graphics.rasterClipEnable = true; + } + + if (this.field1841 != null && this.field1841[var1] != -1) + { + if (this.field1840 != null && this.field1840[var1] != -1) + { + var20 = this.field1840[var1] & 255; + var17 = this.field1844[var20]; + var18 = this.field1865[var20]; + var19 = this.field1846[var20]; + } + else + { + var17 = var5; + var18 = var6; + var19 = var7; + } + + if (this.field1823[var1] == -1) + { + graphics.rasterTextureAffine(var14, var15, var16, var11, var12, var13, this.field1856[var1], this.field1856[var1], this.field1856[var1], yViewportBuffer[var17], yViewportBuffer[var18], yViewportBuffer[var19], field1839[var17], field1839[var18], field1839[var19], field1869[var17], field1869[var18], field1869[var19], this.field1841[var1]); + } + else + { + graphics.rasterTextureAffine(var14, var15, var16, var11, var12, var13, xViewportBuffer[0], xViewportBuffer[1], xViewportBuffer[2], yViewportBuffer[var17], yViewportBuffer[var18], yViewportBuffer[var19], field1839[var17], field1839[var18], field1839[var19], field1869[var17], field1869[var18], field1869[var19], this.field1841[var1]); + } + } + else if (this.field1823[var1] == -1) + { + int[] field1889 = graphics.colorPalette; + graphics.rasterFlat(var14, var15, var16, var11, var12, var13, field1889[this.field1856[var1]]); + } + else + { + graphics.rasterGouraud(var14, var15, var16, var11, var12, var13, xViewportBuffer[0], xViewportBuffer[1], xViewportBuffer[2]); + } + } + + if (var4 == 4) + { + if (var11 < 0 || var12 < 0 || var13 < 0 || var11 > graphics.rasterClipX || var12 > graphics.rasterClipX || var13 > graphics.rasterClipX || field1831[3] < 0 || field1831[3] > graphics.rasterClipX) + { + graphics.rasterClipEnable = true; + } + + if (this.field1841 != null && this.field1841[var1] != -1) + { + if (this.field1840 != null && this.field1840[var1] != -1) + { + var20 = this.field1840[var1] & 255; + var17 = this.field1844[var20]; + var18 = this.field1865[var20]; + var19 = this.field1846[var20]; + } + else + { + var17 = var5; + var18 = var6; + var19 = var7; + } + + short var21 = this.field1841[var1]; + if (this.field1823[var1] == -1) + { + graphics.rasterTextureAffine(var14, var15, var16, var11, var12, var13, this.field1856[var1], this.field1856[var1], this.field1856[var1], yViewportBuffer[var17], yViewportBuffer[var18], yViewportBuffer[var19], field1839[var17], field1839[var18], field1839[var19], field1869[var17], field1869[var18], field1869[var19], var21); + graphics.rasterTextureAffine(var14, var16, field1837[3], var11, var13, field1831[3], this.field1856[var1], this.field1856[var1], this.field1856[var1], yViewportBuffer[var17], yViewportBuffer[var18], yViewportBuffer[var19], field1839[var17], field1839[var18], field1839[var19], field1869[var17], field1869[var18], field1869[var19], var21); + } + else + { + graphics.rasterTextureAffine(var14, var15, var16, var11, var12, var13, xViewportBuffer[0], xViewportBuffer[1], xViewportBuffer[2], yViewportBuffer[var17], yViewportBuffer[var18], yViewportBuffer[var19], field1839[var17], field1839[var18], field1839[var19], field1869[var17], field1869[var18], field1869[var19], var21); + graphics.rasterTextureAffine(var14, var16, field1837[3], var11, var13, field1831[3], xViewportBuffer[0], xViewportBuffer[2], xViewportBuffer[3], yViewportBuffer[var17], yViewportBuffer[var18], yViewportBuffer[var19], field1839[var17], field1839[var18], field1839[var19], field1869[var17], field1869[var18], field1869[var19], var21); + } + } + else if (this.field1823[var1] == -1) + { + int[] field1889 = graphics.colorPalette; + var17 = field1889[this.field1856[var1]]; + graphics.rasterFlat(var14, var15, var16, var11, var12, var13, var17); + graphics.rasterFlat(var14, var16, field1837[3], var11, var13, field1831[3], var17); + } + else + { + graphics.rasterGouraud(var14, var15, var16, var11, var12, var13, xViewportBuffer[0], xViewportBuffer[1], xViewportBuffer[2]); + graphics.rasterGouraud(var14, var16, field1837[3], var11, var13, field1831[3], xViewportBuffer[0], xViewportBuffer[2], xViewportBuffer[3]); + } + } + + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/item/RSTextureProvider.java b/src/main/java/net/runelite/cache/item/RSTextureProvider.java new file mode 100644 index 0000000..a38f14d --- /dev/null +++ b/src/main/java/net/runelite/cache/item/RSTextureProvider.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.item; + +import net.runelite.cache.definitions.TextureDefinition; +import net.runelite.cache.definitions.providers.SpriteProvider; +import net.runelite.cache.definitions.providers.TextureProvider; + +public class RSTextureProvider +{ + private final SpriteProvider spriteProvider; + TextureDefinition[] textures; + int maxSize; + int size; + double brightness; + int width; + + public RSTextureProvider(TextureProvider textureProvider, SpriteProvider spriteProvider) + { + this.spriteProvider = spriteProvider; + this.size = 0; + this.brightness = 1.0D; + this.width = 128; + this.maxSize = 20; + this.size = this.maxSize; + this.brightness = 0.8D; + this.width = 128; + + int max = -1; + for (TextureDefinition textureDefinition : textureProvider.provide()) + { + if (textureDefinition.getId() > max) + { + max = textureDefinition.getId(); + } + } + + textures = new TextureDefinition[max + 1]; + for (TextureDefinition textureDefinition : textureProvider.provide()) + { + textures[textureDefinition.getId()] = textureDefinition; + } + } + + public int[] load(int var1) + { + TextureDefinition var2 = this.textures[var1]; + if (var2 != null) + { + if (var2.pixels != null) + { + return var2.pixels; + } + + boolean var3 = var2.method2680(this.brightness, this.width, spriteProvider); + return var2.pixels; + } + + return null; + } + + + public int getAverageTextureRGB(int var1) + { + return this.textures[var1] != null ? this.textures[var1].field1777 : 0; + } + + + public boolean vmethod3057(int var1) + { + return this.textures[var1].field1778; + } + + + public boolean vmethod3066(int var1) + { + return this.width == 64; + } +} diff --git a/src/main/java/net/runelite/cache/item/Rasterizer2D.java b/src/main/java/net/runelite/cache/item/Rasterizer2D.java new file mode 100644 index 0000000..b3d03fd --- /dev/null +++ b/src/main/java/net/runelite/cache/item/Rasterizer2D.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.item; + +class Rasterizer2D +{ + public int[] graphicsPixels; + public int graphicsPixelsWidth; + public int graphicsPixelsHeight; + public int drawingAreaTop; + public int drawingAreaBottom; + public int draw_region_x; + protected int drawingAreaRight; + + public void setRasterBuffer(int[] var0, int var1, int var2) + { + graphicsPixels = var0; + graphicsPixelsWidth = var1; + graphicsPixelsHeight = var2; + setDrawRegion(0, 0, var1, var2); + } + + public void setDrawRegion(int var0, int var1, int var2, int var3) + { + if (var0 < 0) + { + var0 = 0; + } + + if (var1 < 0) + { + var1 = 0; + } + + if (var2 > graphicsPixelsWidth) + { + var2 = graphicsPixelsWidth; + } + + if (var3 > graphicsPixelsHeight) + { + var3 = graphicsPixelsHeight; + } + + draw_region_x = var0; + drawingAreaTop = var1; + drawingAreaRight = var2; + drawingAreaBottom = var3; + } + + public void reset() + { + int var0 = 0; + + int var1; + for (var1 = graphicsPixelsWidth * graphicsPixelsHeight - 7; var0 < var1; graphicsPixels[var0++] = 0) + { + graphicsPixels[var0++] = 0; + graphicsPixels[var0++] = 0; + graphicsPixels[var0++] = 0; + graphicsPixels[var0++] = 0; + graphicsPixels[var0++] = 0; + graphicsPixels[var0++] = 0; + graphicsPixels[var0++] = 0; + } + + for (var1 += 7; var0 < var1; graphicsPixels[var0++] = 0) + { + ; + } + + } + +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/item/Renderable.java b/src/main/java/net/runelite/cache/item/Renderable.java new file mode 100644 index 0000000..e1ef1b4 --- /dev/null +++ b/src/main/java/net/runelite/cache/item/Renderable.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.item; + +abstract class Renderable +{ + public int modelHeight; + + protected Renderable() + { + this.modelHeight = 1000; + } +} diff --git a/src/main/java/net/runelite/cache/item/SpritePixels.java b/src/main/java/net/runelite/cache/item/SpritePixels.java new file mode 100644 index 0000000..ed8be85 --- /dev/null +++ b/src/main/java/net/runelite/cache/item/SpritePixels.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2018, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.item; + +import java.awt.image.BufferedImage; + +class Sprite +{ + public int[] pixels; + public int width; + public int height; + public int offsetX; + int offsetY; + + public Sprite(int[] var1, int var2, int var3) + { + this.pixels = var1; + this.width = var2; + this.height = var3; + this.offsetY = 0; + this.offsetX = 0; + } + + public Sprite(int var1, int var2) + { + this(new int[var2 * var1], var1, var2); + } + + public void drawBorder(int color) + { + int[] newPixels = new int[this.width * this.height]; + int pixelIndex = 0; + + for (int y = 0; y < this.height; ++y) + { + for (int x = 0; x < this.width; ++x) + { + int pixel = this.pixels[pixelIndex]; + if (pixel == 0) + { + // W + if (x > 0 && this.pixels[pixelIndex - 1] != 0) + { + pixel = color; + } + // N + else if (y > 0 && this.pixels[pixelIndex - this.width] != 0) + { + pixel = color; + } + // E + else if (x < this.width - 1 && this.pixels[pixelIndex + 1] != 0) + { + pixel = color; + } + // S + else if (y < this.height - 1 && this.pixels[pixelIndex + this.width] != 0) + { + pixel = color; + } + } + + newPixels[pixelIndex++] = pixel; + } + } + + this.pixels = newPixels; + } + + + public void drawShadow(int color) + { + for (int y = this.height - 1; y > 0; --y) + { + int rowOffset = y * this.width; + + for (int x = this.width - 1; x > 0; --x) + { + // if *this* pixel is black/unset AND the pixel to the NW isn't black/unset + if (this.pixels[x + rowOffset] == 0 && this.pixels[x + rowOffset - 1 - this.width] != 0) + { + this.pixels[x + rowOffset] = color; + } + } + } + + } + + public void drawAtOn(Rasterizer2D graphics, int x, int y) + { + x += this.offsetX; + y += this.offsetY; + int pixelIndex = x + y * graphics.graphicsPixelsWidth; + int deltaIndex = 0; + int height = this.height; + int width = this.width; + int var7 = graphics.graphicsPixelsWidth - width; + int var8 = 0; + if (y < graphics.drawingAreaTop) + { + int deltaY = graphics.drawingAreaTop - y; + height -= deltaY; + y = graphics.drawingAreaTop; + deltaIndex += deltaY * width; + pixelIndex += deltaY * graphics.graphicsPixelsWidth; + } + + if (height + y > graphics.drawingAreaBottom) + { + height -= height + y - graphics.drawingAreaBottom; + } + + if (x < graphics.draw_region_x) + { + int deltaX = graphics.draw_region_x - x; + width -= deltaX; + x = graphics.draw_region_x; + deltaIndex += deltaX; + pixelIndex += deltaX; + var8 += deltaX; + var7 += deltaX; + } + + if (width + x > graphics.drawingAreaRight) + { + int deltaX = width + x - graphics.drawingAreaRight; + width -= deltaX; + var8 += deltaX; + var7 += deltaX; + } + + if (width > 0 && height > 0) + { + method5843(graphics.graphicsPixels, this.pixels, 0, deltaIndex, pixelIndex, width, height, var7, var8); + } + } + + static void method5843(int[] rasterizerPixels, int[] spritePixels, int var2, int var3, int pixelIndex, int width, int height, int var7, int var8) + { + int var9 = -(width >> 2); + width = -(width & 3); + + for (int var10 = -height; var10 < 0; ++var10) + { + for (int i = var9 * 4; i < 0; ++i) + { + var2 = spritePixels[var3++]; + if (var2 != 0) + { + rasterizerPixels[pixelIndex++] = var2; + } + else + { + ++pixelIndex; + } + } + + for (int i = width; i < 0; ++i) + { + var2 = spritePixels[var3++]; + if (var2 != 0) + { + rasterizerPixels[pixelIndex++] = var2; + } + else + { + ++pixelIndex; + } + } + + pixelIndex += var7; + var3 += var8; + } + + } + + public BufferedImage toBufferedImage() + { + int[] transPixels = new int[pixels.length]; + BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + + for (int i = 0; i < pixels.length; i++) + { + if (pixels[i] != 0) + { + transPixels[i] = pixels[i] | 0xff000000; + } + } + + img.setRGB(0, 0, width, height, transPixels, 0, width); + return img; + } + +} diff --git a/src/main/java/net/runelite/cache/models/CircularAngle.java b/src/main/java/net/runelite/cache/models/CircularAngle.java new file mode 100644 index 0000000..b93f1ee --- /dev/null +++ b/src/main/java/net/runelite/cache/models/CircularAngle.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.models; + +public class CircularAngle +{ + private static final double UNIT = Math.PI / 1024d; // How much of the circle each unit of SINE/COSINE is + + public static final int[] SINE = new int[2048]; // sine angles for each of the 2048 units, * 65536 and stored as an int + public static final int[] COSINE = new int[2048]; // cosine + + static + { + for (int i = 0; i < 2048; ++i) + { + SINE[i] = (int) (65536.0D * Math.sin((double) i * UNIT)); + COSINE[i] = (int) (65536.0D * Math.cos((double) i * UNIT)); + } + } +} diff --git a/src/main/java/net/runelite/cache/models/FaceNormal.java b/src/main/java/net/runelite/cache/models/FaceNormal.java new file mode 100644 index 0000000..387db6a --- /dev/null +++ b/src/main/java/net/runelite/cache/models/FaceNormal.java @@ -0,0 +1,8 @@ +package net.runelite.cache.models; + +public class FaceNormal +{ + public int x; + public int y; + public int z; +} diff --git a/src/main/java/net/runelite/cache/models/ObjExporter.java b/src/main/java/net/runelite/cache/models/ObjExporter.java new file mode 100644 index 0000000..8913610 --- /dev/null +++ b/src/main/java/net/runelite/cache/models/ObjExporter.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.models; + +import java.awt.Color; +import java.io.PrintWriter; +import net.runelite.cache.TextureManager; +import net.runelite.cache.definitions.ModelDefinition; +import net.runelite.cache.definitions.TextureDefinition; + +public class ObjExporter +{ + private final TextureManager textureManager; + private final ModelDefinition model; + + public ObjExporter(TextureManager textureManager, ModelDefinition model) + { + this.textureManager = textureManager; + this.model = model; + } + + public void export(PrintWriter objWriter, PrintWriter mtlWriter) + { + model.computeNormals(); + model.computeTextureUVCoordinates(); + + objWriter.println("mtllib " + model.id + ".mtl"); + + objWriter.println("o runescapemodel"); + + for (int i = 0; i < model.vertexCount; ++i) + { + objWriter.println("v " + model.vertexPositionsX[i] + " " + + model.vertexPositionsY[i] * -1 + " " + + model.vertexPositionsZ[i] * -1); + } + + if (model.faceTextures != null) + { + float[][] u = model.faceTextureUCoordinates; + float[][] v = model.faceTextureVCoordinates; + + for (int i = 0; i < model.faceCount; ++i) + { + objWriter.println("vt " + u[i][0] + " " + v[i][0]); + objWriter.println("vt " + u[i][1] + " " + v[i][1]); + objWriter.println("vt " + u[i][2] + " " + v[i][2]); + } + } + + for (VertexNormal normal : model.vertexNormals) + { + objWriter.println("vn " + normal.x + " " + normal.y + " " + normal.z); + } + + for (int i = 0; i < model.faceCount; ++i) + { + int x = model.faceVertexIndices1[i] + 1; + int y = model.faceVertexIndices2[i] + 1; + int z = model.faceVertexIndices3[i] + 1; + + objWriter.println("usemtl m" + i); + if (model.faceTextures != null) + { + objWriter.println("f " + + x + "/" + (i * 3 + 1) + " " + + y + "/" + (i * 3 + 2) + " " + + z + "/" + (i * 3 + 3)); + + } + else + { + objWriter.println("f " + x + " " + y + " " + z); + } + objWriter.println(""); + } + + // Write material + for (int i = 0; i < model.faceCount; ++i) + { + short textureId = -1; + + if (model.faceTextures != null) + { + textureId = model.faceTextures[i]; + } + + mtlWriter.println("newmtl m" + i); + + if (textureId == -1) + { + Color color = rs2hsbToColor(model.faceColors[i]); + + double r = color.getRed() / 255.0; + double g = color.getGreen() / 255.0; + double b = color.getBlue() / 255.0; + + mtlWriter.println("Kd " + r + " " + g + " " + b); + } + else + { + TextureDefinition texture = textureManager.findTexture(textureId); + assert texture != null; + + mtlWriter.println("map_Kd sprite/" + texture.getFileIds()[0] + "-0.png"); + } + + int alpha = 0; + + if (model.faceAlphas != null) + { + alpha = model.faceAlphas[i] & 0xFF; + } + + if (alpha != 0) + { + mtlWriter.println("d " + (alpha / 255.0)); + } + } + } + + private static Color rs2hsbToColor(int hsb) + { + int decode_hue = (hsb >> 10) & 0x3f; + int decode_saturation = (hsb >> 7) & 0x07; + int decode_brightness = (hsb & 0x7f); + return Color.getHSBColor((float) decode_hue / 63, (float) decode_saturation / 7, (float) decode_brightness / 127); + } +} diff --git a/src/main/java/net/runelite/cache/models/Vector3f.java b/src/main/java/net/runelite/cache/models/Vector3f.java new file mode 100644 index 0000000..a93e1cd --- /dev/null +++ b/src/main/java/net/runelite/cache/models/Vector3f.java @@ -0,0 +1,103 @@ +package net.runelite.cache.models; + +public class Vector3f +{ + public float x; + public float y; + public float z; + + public Vector3f() + { + } + + public Vector3f(float x, float y, float z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public Vector3f(Vector3f other) + { + this.x = other.x; + this.y = other.y; + this.z = other.z; + } + + @Override + public String toString() + { + return "Vector3f{" + "x=" + x + ", y=" + y + ", z=" + z + '}'; + } + + @Override + public int hashCode() + { + int hash = 7; + hash = 23 * hash + Float.floatToIntBits(this.x); + hash = 23 * hash + Float.floatToIntBits(this.y); + hash = 23 * hash + Float.floatToIntBits(this.z); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final Vector3f other = (Vector3f) obj; + if (Float.floatToIntBits(this.x) != Float.floatToIntBits(other.x)) + { + return false; + } + if (Float.floatToIntBits(this.y) != Float.floatToIntBits(other.y)) + { + return false; + } + if (Float.floatToIntBits(this.z) != Float.floatToIntBits(other.z)) + { + return false; + } + return true; + } + + public float getX() + { + return x; + } + + public void setX(float x) + { + this.x = x; + } + + public float getY() + { + return y; + } + + public void setY(float y) + { + this.y = y; + } + + public float getZ() + { + return z; + } + + public void setZ(float z) + { + this.z = z; + } +} diff --git a/src/main/java/net/runelite/cache/models/VertexNormal.java b/src/main/java/net/runelite/cache/models/VertexNormal.java new file mode 100644 index 0000000..b1635ed --- /dev/null +++ b/src/main/java/net/runelite/cache/models/VertexNormal.java @@ -0,0 +1,30 @@ +package net.runelite.cache.models; + +public class VertexNormal +{ + public int x; + public int y; + public int z; + public int magnitude; + + public Vector3f normalize() + { + Vector3f v = new Vector3f(); + + int length = (int) Math.sqrt((double) (x * x + y * y + z * z)); + if (length == 0) + { + length = 1; + } + + v.x = (float) x / length; + v.y = (float) y / length; + v.z = (float) z / length; + + assert v.x >= -1f && v.x <= 1f; + assert v.y >= -1f && v.y <= 1f; + assert v.z >= -1f && v.z <= 1f; + + return v; + } +} diff --git a/src/main/java/net/runelite/cache/region/HeightCalc.java b/src/main/java/net/runelite/cache/region/HeightCalc.java new file mode 100644 index 0000000..18b291e --- /dev/null +++ b/src/main/java/net/runelite/cache/region/HeightCalc.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2015 Kyle Friz + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package net.runelite.cache.region; + +/** + * @author Kyle Friz + * @since Feb 20, 2016 + */ +public class HeightCalc +{ + private static final int JAGEX_CIRCULAR_ANGLE = 2048; + private static final double ANGULAR_RATIO = 360D / JAGEX_CIRCULAR_ANGLE; + private static final double JAGEX_RADIAN = Math.toRadians(ANGULAR_RATIO); + + private static final int[] SIN = new int[JAGEX_CIRCULAR_ANGLE]; + private static final int[] COS = new int[JAGEX_CIRCULAR_ANGLE]; + + static + { + for (int i = 0; i < JAGEX_CIRCULAR_ANGLE; i++) + { + SIN[i] = (int) (65536.0D * Math.sin((double) i * JAGEX_RADIAN)); + COS[i] = (int) (65536.0D * Math.cos((double) i * JAGEX_RADIAN)); + } + } + + public static int calculate(int x, int y) + { + int n = interpolateNoise(x + 45365, y + 91923, 4) - 128 + + (interpolateNoise(10294 + x, y + 37821, 2) - 128 >> 1) + + (interpolateNoise(x, y, 1) - 128 >> 2); + n = 35 + (int) ((double) n * 0.3D); + if (n < 10) + { + n = 10; + } + else if (n > 60) + { + n = 60; + } + + return n; + } + + public static int interpolateNoise(int x, int y, int frequency) + { + int intX = x / frequency; + int fracX = x & frequency - 1; + int intY = y / frequency; + int fracY = y & frequency - 1; + int v1 = smoothedNoise1(intX, intY); + int v2 = smoothedNoise1(intX + 1, intY); + int v3 = smoothedNoise1(intX, intY + 1); + int v4 = smoothedNoise1(1 + intX, 1 + intY); + int i1 = interpolate(v1, v2, fracX, frequency); + int i2 = interpolate(v3, v4, fracX, frequency); + return interpolate(i1, i2, fracY, frequency); + } + + public static int smoothedNoise1(int x, int y) + { + int corners = noise(x - 1, y - 1) + noise(x + 1, y - 1) + noise(x - 1, 1 + y) + noise(x + 1, y + 1); + int sides = noise(x - 1, y) + noise(1 + x, y) + noise(x, y - 1) + noise(x, 1 + y); + int center = noise(x, y); + return center / 4 + sides / 8 + corners / 16; + } + + public static int noise(int x, int y) + { + int n = x + y * 57; + n ^= n << 13; + return ((n * (n * n * 15731 + 789221) + 1376312589) & Integer.MAX_VALUE) >> 19 & 255; + } + + public static int interpolate(int a, int b, int x, int y) + { + int f = 65536 - COS[1024 * x / y] >> 1; + return (f * b >> 16) + (a * (65536 - f) >> 16); + } + +} diff --git a/src/main/java/net/runelite/cache/region/Location.java b/src/main/java/net/runelite/cache/region/Location.java new file mode 100644 index 0000000..7cf59f8 --- /dev/null +++ b/src/main/java/net/runelite/cache/region/Location.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.region; + +import lombok.Value; + +@Value +public class Location +{ + private final int id; + private final int type; + private final int orientation; + private final Position position; +} diff --git a/src/main/java/net/runelite/cache/region/Position.java b/src/main/java/net/runelite/cache/region/Position.java new file mode 100644 index 0000000..d80144c --- /dev/null +++ b/src/main/java/net/runelite/cache/region/Position.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.region; + +public class Position +{ + private final int x; + private final int y; + private final int z; + + public Position(int x, int y, int z) + { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public String toString() + { + return "Position{" + "x=" + x + ", y=" + y + ", z=" + z + '}'; + } + + @Override + public int hashCode() + { + int hash = 7; + hash = 67 * hash + this.x; + hash = 67 * hash + this.y; + hash = 67 * hash + this.z; + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + final Position other = (Position) obj; + if (this.x != other.x) + { + return false; + } + if (this.y != other.y) + { + return false; + } + if (this.z != other.z) + { + return false; + } + return true; + } + + public int getX() + { + return x; + } + + public int getY() + { + return y; + } + + public int getZ() + { + return z; + } +} diff --git a/src/main/java/net/runelite/cache/region/Region.java b/src/main/java/net/runelite/cache/region/Region.java new file mode 100644 index 0000000..7dbda27 --- /dev/null +++ b/src/main/java/net/runelite/cache/region/Region.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.region; + +import java.util.ArrayList; +import java.util.List; +import net.runelite.cache.definitions.LocationsDefinition; +import net.runelite.cache.definitions.MapDefinition; +import net.runelite.cache.definitions.MapDefinition.Tile; + +public class Region +{ + + public static final int X = 64; + public static final int Y = 64; + public static final int Z = 4; + + private final int regionID; + private final int baseX; + private final int baseY; + + private final int[][][] tileHeights = new int[Z][X][Y]; + private final byte[][][] tileSettings = new byte[Z][X][Y]; + private final byte[][][] overlayIds = new byte[Z][X][Y]; + private final byte[][][] overlayPaths = new byte[Z][X][Y]; + private final byte[][][] overlayRotations = new byte[Z][X][Y]; + private final byte[][][] underlayIds = new byte[Z][X][Y]; + + private final List locations = new ArrayList<>(); + + public Region(int id) + { + this.regionID = id; + this.baseX = ((id >> 8) & 0xFF) << 6; // local coords are in bottom 6 bits (64*64) + this.baseY = (id & 0xFF) << 6; + } + + public Region(int x, int y) + { + this.regionID = x << 8 | y; + this.baseX = x << 6; + this.baseY = y << 6; + } + + public void loadTerrain(MapDefinition map) + { + Tile[][][] tiles = map.getTiles(); + for (int z = 0; z < Z; z++) + { + for (int x = 0; x < X; x++) + { + for (int y = 0; y < Y; y++) + { + Tile tile = tiles[z][x][y]; + + if (tile.height == null) + { + if (z == 0) + { + tileHeights[0][x][y] = -HeightCalc.calculate(baseX + x + 0xe3b7b, baseY + y + 0x87cce) * 8; + } + else + { + tileHeights[z][x][y] = tileHeights[z - 1][x][y] - 240; + } + } + else + { + int height = tile.getHeight(); + if (height == 1) + { + height = 0; + } + + if (z == 0) + { + tileHeights[0][x][y] = -height * 8; + } + else + { + tileHeights[z][x][y] = tileHeights[z - 1][x][y] - height * 8; + } + } + + overlayIds[z][x][y] = tile.getOverlayId(); + overlayPaths[z][x][y] = tile.getOverlayPath(); + overlayRotations[z][x][y] = tile.getOverlayRotation(); + + tileSettings[z][x][y] = tile.getSettings(); + underlayIds[z][x][y] = tile.getUnderlayId(); + } + } + } + } + + public void loadLocations(LocationsDefinition locs) + { + for (Location loc : locs.getLocations()) + { + Location newLoc = new Location(loc.getId(), loc.getType(), loc.getOrientation(), + new Position(getBaseX() + loc.getPosition().getX(), + getBaseY() + loc.getPosition().getY(), + loc.getPosition().getZ())); + locations.add(newLoc); + } + } + + public int getRegionID() + { + return regionID; + } + + public int getBaseX() + { + return baseX; + } + + public int getBaseY() + { + return baseY; + } + + public int getTileHeight(int z, int x, int y) + { + return tileHeights[z][x][y]; + } + + public byte getTileSetting(int z, int x, int y) + { + return tileSettings[z][x][y]; + } + + public int getOverlayId(int z, int x, int y) + { + return overlayIds[z][x][y] & 0xFF; + } + + public byte getOverlayPath(int z, int x, int y) + { + return overlayPaths[z][x][y]; + } + + public byte getOverlayRotation(int z, int x, int y) + { + return overlayRotations[z][x][y]; + } + + public int getUnderlayId(int z, int x, int y) + { + return underlayIds[z][x][y] & 0xFF; + } + + public List getLocations() + { + return locations; + } + + public int getRegionX() + { + return baseX >> 6; + } + + public int getRegionY() + { + return baseY >> 6; + } +} diff --git a/src/main/java/net/runelite/cache/region/RegionLoader.java b/src/main/java/net/runelite/cache/region/RegionLoader.java new file mode 100644 index 0000000..a15e25a --- /dev/null +++ b/src/main/java/net/runelite/cache/region/RegionLoader.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.region; + +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import net.runelite.cache.IndexType; +import net.runelite.cache.definitions.LocationsDefinition; +import net.runelite.cache.definitions.MapDefinition; +import net.runelite.cache.definitions.loaders.LocationsLoader; +import net.runelite.cache.definitions.loaders.MapLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; +import net.runelite.cache.util.XteaKeyManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RegionLoader +{ + private static final Logger logger = LoggerFactory.getLogger(RegionLoader.class); + + private static final int MAX_REGION = 32768; + + private final Store store; + private final Index index; + private final XteaKeyManager keyManager; + + private final Map regions = new HashMap<>(); + private Region lowestX = null, lowestY = null; + private Region highestX = null, highestY = null; + + public RegionLoader(Store store) + { + this.store = store; + index = store.getIndex(IndexType.MAPS); + keyManager = new XteaKeyManager(); + keyManager.loadKeys(); + } + + public void loadRegions() throws IOException + { + for (int i = 0; i < MAX_REGION; ++i) + { + Region region = this.loadRegionFromArchive(i); + if (region != null) + { + regions.put(i, region); + } + } + } + + public Region loadRegionFromArchive(int i) throws IOException + { + int x = i >> 8; + int y = i & 0xFF; + + Storage storage = store.getStorage(); + Archive map = index.findArchiveByName("m" + x + "_" + y); + Archive land = index.findArchiveByName("l" + x + "_" + y); + + assert (map == null) == (land == null); + + if (map == null || land == null) + { + return null; + } + + byte[] data = map.decompress(storage.loadArchive(map)); + + MapDefinition mapDef = new MapLoader().load(x, y, data); + + Region region = new Region(i); + region.loadTerrain(mapDef); + + int[] keys = keyManager.getKeys(i); + if (keys != null) + { + try + { + data = land.decompress(storage.loadArchive(land), keys); + LocationsDefinition locDef = new LocationsLoader().load(x, y, data); + region.loadLocations(locDef); + } + catch (IOException ex) + { + logger.debug("Can't decrypt region " + i, ex); + } + } + + return region; + } + + public void calculateBounds() + { + for (Region region : regions.values()) + { + if (lowestX == null || region.getBaseX() < lowestX.getBaseX()) + { + lowestX = region; + } + + if (highestX == null || region.getBaseX() > highestX.getBaseX()) + { + highestX = region; + } + + if (lowestY == null || region.getBaseY() < lowestY.getBaseY()) + { + lowestY = region; + } + + if (highestY == null || region.getBaseY() > highestY.getBaseY()) + { + highestY = region; + } + } + } + + public Collection getRegions() + { + return regions.values(); + } + + public Region findRegionForWorldCoordinates(int x, int y) + { + x >>>= 6; + y >>>= 6; + return regions.get((x << 8) | y); + } + + public Region getLowestX() + { + return lowestX; + } + + public Region getLowestY() + { + return lowestY; + } + + public Region getHighestX() + { + return highestX; + } + + public Region getHighestY() + { + return highestY; + } +} diff --git a/src/main/java/net/runelite/cache/script/Instruction.java b/src/main/java/net/runelite/cache/script/Instruction.java new file mode 100644 index 0000000..b369c97 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/Instruction.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.script; + +public class Instruction +{ + private final int opcode; + private String name; + + public Instruction(int opcode) + { + this.opcode = opcode; + } + + public int getOpcode() + { + return opcode; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } +} diff --git a/src/main/java/net/runelite/cache/script/Instructions.java b/src/main/java/net/runelite/cache/script/Instructions.java new file mode 100644 index 0000000..f7882e6 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/Instructions.java @@ -0,0 +1,557 @@ +/* + * Copyright (c) 2017, Adam + * Copyright (c) 2018-2019, Hunter WB + * Copyright (c) 2019, Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.script; + +import java.util.HashMap; +import java.util.Map; +import static net.runelite.cache.script.Opcodes.*; + +public class Instructions +{ + private final Map instructions = new HashMap<>(); + private final Map instructionsByName = new HashMap<>(); + + public void init() + { + add(ICONST, "iconst"); + add(GET_VARP, "get_varp"); + add(SET_VARP, "set_varp"); + add(SCONST, "sconst"); + add(JUMP, "jump"); + add(IF_ICMPNE, "if_icmpne"); + add(IF_ICMPEQ, "if_icmpeq"); + add(IF_ICMPLT, "if_icmplt"); + add(IF_ICMPGT, "if_icmpgt"); + add(RETURN, "return"); + add(GET_VARBIT, "get_varbit"); + add(SET_VARBIT, "set_varbit"); + add(IF_ICMPLE, "if_icmple"); + add(IF_ICMPGE, "if_icmpge"); + add(ILOAD, "iload"); + add(ISTORE, "istore"); + add(SLOAD, "sload"); + add(SSTORE, "sstore"); + add(JOIN_STRING, "join_string"); + add(POP_INT, "pop_int"); + add(POP_STRING, "pop_string"); + add(INVOKE, "invoke"); + add(GET_VARC_INT, "get_varc_int"); + add(SET_VARC_INT, "set_varc_int"); + add(DEFINE_ARRAY, "define_array"); + add(GET_ARRAY_INT, "get_array_int"); + add(SET_ARRAY_INT, "set_array_int"); + add(GET_VARC_STRING_OLD, "get_varc_string_old"); + add(SET_VARC_STRING_OLD, "set_varc_string_old"); + add(GET_VARC_STRING, "get_varc_string"); + add(SET_VARC_STRING, "set_varc_string"); + add(SWITCH, "switch"); + add(CC_CREATE, "cc_create"); + add(CC_DELETE, "cc_delete"); + add(CC_DELETEALL, "cc_deleteall"); + add(CC_FIND, "cc_find"); + add(IF_FIND, "if_find"); + add(CC_SETPOSITION, "cc_setposition"); + add(CC_SETSIZE, "cc_setsize"); + add(CC_SETHIDE, "cc_sethide"); + add(CC_SETNOCLICKTHROUGH, "cc_setnoclickthrough"); + add(CC_SETNOSCROLLTHROUGH, "cc_setnoscrollthrough"); + add(CC_SETSCROLLPOS, "cc_setscrollpos"); + add(CC_SETCOLOUR, "cc_setcolour"); + add(CC_SETFILL, "cc_setfill"); + add(CC_SETTRANS, "cc_settrans"); + add(CC_SETLINEWID, "cc_setlinewid"); + add(CC_SETGRAPHIC, "cc_setgraphic"); + add(CC_SET2DANGLE, "cc_set2dangle"); + add(CC_SETTILING, "cc_settiling"); + add(CC_SETMODEL, "cc_setmodel"); + add(CC_SETMODELANGLE, "cc_setmodelangle"); + add(CC_SETMODELANIM, "cc_setmodelanim"); + add(CC_SETMODELORTHOG, "cc_setmodelorthog"); + add(CC_SETTEXT, "cc_settext"); + add(CC_SETTEXTFONT, "cc_settextfont"); + add(CC_SETTEXTALIGN, "cc_settextalign"); + add(CC_SETTEXTSHADOW, "cc_settextshadow"); + add(CC_SETOUTLINE, "cc_setoutline"); + add(CC_SETGRAPHICSHADOW, "cc_setgraphicshadow"); + add(CC_SETVFLIP, "cc_setvflip"); + add(CC_SETHFLIP, "cc_sethflip"); + add(CC_SETSCROLLSIZE, "cc_setscrollsize"); + add(CC_RESUME_PAUSEBUTTON, "cc_resume_pausebutton"); + add(CC_SETFILLCOLOUR, "cc_setfillcolour"); + add(CC_SETLINEDIRECTION, "cc_setlinedirection"); + add(CC_SETMODELTRANSPARENT, "cc_setmodeltransparent"); + add(CC_SETOBJECT, "cc_setobject"); + add(CC_SETNPCHEAD, "cc_setnpchead"); + add(CC_SETPLAYERHEAD_SELF, "cc_setplayerhead_self"); + add(CC_SETOBJECT_NONUM, "cc_setobject_nonum"); + add(CC_SETOBJECT_ALWAYS_NUM, "cc_setobject_always_num"); + add(CC_SETOP, "cc_setop"); + add(CC_SETDRAGGABLE, "cc_setdraggable"); + add(CC_SETDRAGGABLEBEHAVIOR, "cc_setdraggablebehavior"); + add(CC_SETDRAGDEADZONE, "cc_setdragdeadzone"); + add(CC_SETDRAGDEADTIME, "cc_setdragdeadtime"); + add(CC_SETOPBASE, "cc_setopbase"); + add(CC_SETTARGETVERB, "cc_settargetverb"); + add(CC_CLEAROPS, "cc_clearops"); + add(CC_SETOPKEY, "cc_setopkey"); + add(CC_SETOPTKEY, "cc_setoptkey"); + add(CC_SETOPKEYRATE, "cc_setopkeyrate"); + add(CC_SETOPTKEYRATE, "cc_setoptkeyrate"); + add(CC_SETOPKEYIGNOREHELD, "cc_setopkeyignoreheld"); + add(CC_SETOPTKEYIGNOREHELD, "cc_setoptkeyignoreheld"); + add(CC_SETONCLICK, "cc_setonclick"); + add(CC_SETONHOLD, "cc_setonhold"); + add(CC_SETONRELEASE, "cc_setonrelease"); + add(CC_SETONMOUSEOVER, "cc_setonmouseover"); + add(CC_SETONMOUSELEAVE, "cc_setonmouseleave"); + add(CC_SETONDRAG, "cc_setondrag"); + add(CC_SETONTARGETLEAVE, "cc_setontargetleave"); + add(CC_SETONVARTRANSMIT, "cc_setonvartransmit"); + add(CC_SETONTIMER, "cc_setontimer"); + add(CC_SETONOP, "cc_setonop"); + add(CC_SETONDRAGCOMPLETE, "cc_setondragcomplete"); + add(CC_SETONCLICKREPEAT, "cc_setonclickrepeat"); + add(CC_SETONMOUSEREPEAT, "cc_setonmouserepeat"); + add(CC_SETONINVTRANSMIT, "cc_setoninvtransmit"); + add(CC_SETONSTATTRANSMIT, "cc_setonstattransmit"); + add(CC_SETONTARGETENTER, "cc_setontargetenter"); + add(CC_SETONSCROLLWHEEL, "cc_setonscrollwheel"); + add(CC_SETONCHATTRANSMIT, "cc_setonchattransmit"); + add(CC_SETONKEY, "cc_setonkey"); + add(CC_SETONFRIENDTRANSMIT, "cc_setonfriendtransmit"); + add(CC_SETONCLANTRANSMIT, "cc_setonclantransmit"); + add(CC_SETONMISCTRANSMIT, "cc_setonmisctransmit"); + add(CC_SETONDIALOGABORT, "cc_setondialogabort"); + add(CC_SETONSUBCHANGE, "cc_setonsubchange"); + add(CC_SETONSTOCKTRANSMIT, "cc_setonstocktransmit"); + add(CC_SETONRESIZE, "cc_setonresize"); + add(CC_GETX, "cc_getx"); + add(CC_GETY, "cc_gety"); + add(CC_GETWIDTH, "cc_getwidth"); + add(CC_GETHEIGHT, "cc_getheight"); + add(CC_GETHIDE, "cc_gethide"); + add(CC_GETLAYER, "cc_getlayer"); + add(CC_GETSCROLLX, "cc_getscrollx"); + add(CC_GETSCROLLY, "cc_getscrolly"); + add(CC_GETTEXT, "cc_gettext"); + add(CC_GETSCROLLWIDTH, "cc_getscrollwidth"); + add(CC_GETSCROLLHEIGHT, "cc_getscrollheight"); + add(CC_GETMODELZOOM, "cc_getmodelzoom"); + add(CC_GETMODELANGLE_X, "cc_getmodelangle_x"); + add(CC_GETMODELANGLE_Z, "cc_getmodelangle_z"); + add(CC_GETMODELANGLE_Y, "cc_getmodelangle_y"); + add(CC_GETTRANS, "cc_gettrans"); + add(CC_GETCOLOUR, "cc_getcolour"); + add(CC_GETFILLCOLOUR, "cc_getfillcolour"); + add(CC_GETMODELTRANSPARENT, "cc_getmodeltransparent"); + add(CC_GETINVOBJECT, "cc_getinvobject"); + add(CC_GETINVCOUNT, "cc_getinvcount"); + add(CC_GETID, "cc_getid"); + add(CC_GETTARGETMASK, "cc_gettargetmask"); + add(CC_GETOP, "cc_getop"); + add(CC_GETOPBASE, "cc_getopbase"); + add(CC_CALLONRESIZE, "cc_callonresize"); + add(IF_SETPOSITION, "if_setposition"); + add(IF_SETSIZE, "if_setsize"); + add(IF_SETHIDE, "if_sethide"); + add(IF_SETNOCLICKTHROUGH, "if_setnoclickthrough"); + add(IF_SETSCROLLPOS, "if_setscrollpos"); + add(IF_SETCOLOUR, "if_setcolour"); + add(IF_SETFILL, "if_setfill"); + add(IF_SETTRANS, "if_settrans"); + add(IF_SETLINEWID, "if_setlinewid"); + add(IF_SETGRAPHIC, "if_setgraphic"); + add(IF_SET2DANGLE, "if_set2dangle"); + add(IF_SETTILING, "if_settiling"); + add(IF_SETMODEL, "if_setmodel"); + add(IF_SETMODELANGLE, "if_setmodelangle"); + add(IF_SETMODELANIM, "if_setmodelanim"); + add(IF_SETMODELORTHOG, "if_setmodelorthog"); + add(IF_SETTEXT, "if_settext"); + add(IF_SETTEXTFONT, "if_settextfont"); + add(IF_SETTEXTALIGN, "if_settextalign"); + add(IF_SETTEXTSHADOW, "if_settextshadow"); + add(IF_SETOUTLINE, "if_setoutline"); + add(IF_SETGRAPHICSHADOW, "if_setgraphicshadow"); + add(IF_SETVFLIP, "if_setvflip"); + add(IF_SETHFLIP, "if_sethflip"); + add(IF_SETSCROLLSIZE, "if_setscrollsize"); + add(IF_RESUME_PAUSEBUTTON, "if_resume_pausebutton"); + add(IF_SETFILLCOLOUR, "if_setfillcolour"); + add(IF_SETLINEDIRECTION, "if_setlinedirection"); + add(IF_SETMODELTRANSPARENT, "if_setmodeltransparent"); + add(IF_SETOBJECT, "if_setobject"); + add(IF_SETNPCHEAD, "if_setnpchead"); + add(IF_SETPLAYERHEAD_SELF, "if_setplayerhead_self"); + add(IF_SETOBJECT_NONUM, "if_setobject_nonum"); + add(IF_SETOBJECT_ALWAYS_NUM, "if_setobject_always_num"); + add(IF_SETOP, "if_setop"); + add(IF_SETDRAGGABLE, "if_setdraggable"); + add(IF_SETDRAGGABLEBEHAVIOR, "if_setdraggablebehavior"); + add(IF_SETDRAGDEADZONE, "if_setdragdeadzone"); + add(IF_SETDRAGDEADTIME, "if_setdragdeadtime"); + add(IF_SETOPBASE, "if_setopbase"); + add(IF_SETTARGETVERB, "if_settargetverb"); + add(IF_CLEAROPS, "if_clearops"); + add(IF_SETOPKEY, "if_setopkey"); + add(IF_SETOPTKEY, "if_setoptkey"); + add(IF_SETOPKEYRATE, "if_setopkeyrate"); + add(IF_SETOPTKEYRATE, "if_setoptkeyrate"); + add(IF_SETOPKEYIGNOREHELD, "if_setopkeyignoreheld"); + add(IF_SETOPTKEYIGNOREHELD, "if_setoptkeyignoreheld"); + add(IF_SETONCLICK, "if_setonclick"); + add(IF_SETONHOLD, "if_setonhold"); + add(IF_SETONRELEASE, "if_setonrelease"); + add(IF_SETONMOUSEOVER, "if_setonmouseover"); + add(IF_SETONMOUSELEAVE, "if_setonmouseleave"); + add(IF_SETONDRAG, "if_setondrag"); + add(IF_SETONTARGETLEAVE, "if_setontargetleave"); + add(IF_SETONVARTRANSMIT, "if_setonvartransmit"); + add(IF_SETONTIMER, "if_setontimer"); + add(IF_SETONOP, "if_setonop"); + add(IF_SETONDRAGCOMPLETE, "if_setondragcomplete"); + add(IF_SETONCLICKREPEAT, "if_setonclickrepeat"); + add(IF_SETONMOUSEREPEAT, "if_setonmouserepeat"); + add(IF_SETONINVTRANSMIT, "if_setoninvtransmit"); + add(IF_SETONSTATTRANSMIT, "if_setonstattransmit"); + add(IF_SETONTARGETENTER, "if_setontargetenter"); + add(IF_SETONSCROLLWHEEL, "if_setonscrollwheel"); + add(IF_SETONCHATTRANSMIT, "if_setonchattransmit"); + add(IF_SETONKEY, "if_setonkey"); + add(IF_SETONFRIENDTRANSMIT, "if_setonfriendtransmit"); + add(IF_SETONCLANTRANSMIT, "if_setonclantransmit"); + add(IF_SETONMISCTRANSMIT, "if_setonmisctransmit"); + add(IF_SETONDIALOGABORT, "if_setondialogabort"); + add(IF_SETONSUBCHANGE, "if_setonsubchange"); + add(IF_SETONSTOCKTRANSMIT, "if_setonstocktransmit"); + add(IF_SETONRESIZE, "if_setonresize"); + add(IF_GETX, "if_getx"); + add(IF_GETY, "if_gety"); + add(IF_GETWIDTH, "if_getwidth"); + add(IF_GETHEIGHT, "if_getheight"); + add(IF_GETHIDE, "if_gethide"); + add(IF_GETLAYER, "if_getlayer"); + add(IF_GETSCROLLX, "if_getscrollx"); + add(IF_GETSCROLLY, "if_getscrolly"); + add(IF_GETTEXT, "if_gettext"); + add(IF_GETSCROLLWIDTH, "if_getscrollwidth"); + add(IF_GETSCROLLHEIGHT, "if_getscrollheight"); + add(IF_GETMODELZOOM, "if_getmodelzoom"); + add(IF_GETMODELANGLE_X, "if_getmodelangle_x"); + add(IF_GETMODELANGLE_Z, "if_getmodelangle_z"); + add(IF_GETMODELANGLE_Y, "if_getmodelangle_y"); + add(IF_GETTRANS, "if_gettrans"); + add(IF_GETCOLOUR, "if_getcolour"); + add(IF_GETFILLCOLOUR, "if_getfillcolour"); + add(IF_GETMODELTRANSPARENT, "if_getmodeltransparent"); + add(IF_GETINVOBJECT, "if_getinvobject"); + add(IF_GETINVCOUNT, "if_getinvcount"); + add(IF_HASSUB, "if_hassub"); + add(IF_GETTOP, "if_gettop"); + add(IF_GETTARGETMASK, "if_gettargetmask"); + add(IF_GETOP, "if_getop"); + add(IF_GETOPBASE, "if_getopbase"); + add(IF_CALLONRESIZE, "if_callonresize"); + add(MES, "mes"); + add(ANIM, "anim"); + add(IF_CLOSE, "if_close"); + add(RESUME_COUNTDIALOG, "resume_countdialog"); + add(RESUME_NAMEDIALOG, "resume_namedialog"); + add(RESUME_STRINGDIALOG, "resume_stringdialog"); + add(OPPLAYER, "opplayer"); + add(IF_DRAGPICKUP, "if_dragpickup"); + add(CC_DRAGPICKUP, "cc_dragpickup"); + add(MOUSECAM, "mousecam"); + add(GETREMOVEROOFS, "getremoveroofs"); + add(SETREMOVEROOFS, "setremoveroofs"); + add(OPENURL, "openurl"); + add(RESUME_OBJDIALOG, "resume_objdialog"); + add(BUG_REPORT, "bug_report"); + add(SETSHIFTCLICKDROP, "setshiftclickdrop"); + add(SETSHOWMOUSEOVERTEXT, "setshowmouseovertext"); + add(RENDERSELF, "renderself"); + add(SETSHOWMOUSECROSS, "setshowmousecross"); + add(SETSHOWLOADINGMESSAGES, "setshowloadingmessages"); + add(SETTAPTODROP, "settaptodrop"); + add(GETTAPTODROP, "gettaptodrop"); + add(SETOCULUSORBSPEED, "setoculusorbspeed"); + add(GETCANVASSIZE, "getcanvassize"); + add(MOBILE_SETFPS, "mobile_setfps"); + add(MOBILE_OPENSTORE, "mobile_openstore"); + add(MOBILE_OPENSTORECATEGORY, "mobile_openstorecategory"); + add(SETHIDEUSERNAME, "sethideusername"); + add(GETHIDEUSERNAME, "gethideusername"); + add(SETREMEMBERUSERNAME, "setrememberusername"); + add(GETREMEMBERUSERNAME, "getrememberusername"); + add(SETTITLEMUSICENABLED, "settitlemusicenabled"); + add(GETTITLEMUSICENABLED, "gettitlemusicenabled"); + add(SOUND_SYNTH, "sound_synth"); + add(SOUND_SONG, "sound_song"); + add(SOUND_JINGLE, "sound_jingle"); + add(CLIENTCLOCK, "clientclock"); + add(INV_GETOBJ, "inv_getobj"); + add(INV_GETNUM, "inv_getnum"); + add(INV_TOTAL, "inv_total"); + add(INV_SIZE, "inv_size"); + add(STAT, "stat"); + add(STAT_BASE, "stat_base"); + add(STAT_XP, "stat_xp"); + add(COORD, "coord"); + add(COORDX, "coordx"); + add(COORDZ, "coordz"); + add(COORDY, "coordy"); + add(MAP_MEMBERS, "map_members"); + add(INVOTHER_GETOBJ, "invother_getobj"); + add(INVOTHER_GETNUM, "invother_getnum"); + add(INVOTHER_TOTAL, "invother_total"); + add(STAFFMODLEVEL, "staffmodlevel"); + add(REBOOTTIMER, "reboottimer"); + add(MAP_WORLD, "map_world"); + add(RUNENERGY_VISIBLE, "runenergy_visible"); + add(RUNWEIGHT_VISIBLE, "runweight_visible"); + add(PLAYERMOD, "playermod"); + add(WORLDFLAGS, "worldflags"); + add(MOVECOORD, "movecoord"); + add(ENUM_STRING, "enum_string"); + add(ENUM, "enum"); + add(ENUM_GETOUTPUTCOUNT, "enum_getoutputcount"); + add(FRIEND_COUNT, "friend_count"); + add(FRIEND_GETNAME, "friend_getname"); + add(FRIEND_GETWORLD, "friend_getworld"); + add(FRIEND_GETRANK, "friend_getrank"); + add(FRIEND_SETRANK, "friend_setrank"); + add(FRIEND_ADD, "friend_add"); + add(FRIEND_DEL, "friend_del"); + add(IGNORE_ADD, "ignore_add"); + add(IGNORE_DEL, "ignore_del"); + add(FRIEND_TEST, "friend_test"); + add(CLAN_GETCHATDISPLAYNAME, "clan_getchatdisplayname"); + add(CLAN_GETCHATCOUNT, "clan_getchatcount"); + add(CLAN_GETCHATUSERNAME, "clan_getchatusername"); + add(CLAN_GETCHATUSERWORLD, "clan_getchatuserworld"); + add(CLAN_GETCHATUSERRANK, "clan_getchatuserrank"); + add(CLAN_GETCHATMINKICK, "clan_getchatminkick"); + add(CLAN_KICKUSER, "clan_kickuser"); + add(CLAN_GETCHATRANK, "clan_getchatrank"); + add(CLAN_JOINCHAT, "clan_joinchat"); + add(CLAN_LEAVECHAT, "clan_leavechat"); + add(IGNORE_COUNT, "ignore_count"); + add(IGNORE_GETNAME, "ignore_getname"); + add(IGNORE_TEST, "ignore_test"); + add(CLAN_ISSELF, "clan_isself"); + add(CLAN_GETCHATOWNERNAME, "clan_getchatownername"); + add(CLAN_ISFRIEND, "clan_isfriend"); + add(CLAN_ISIGNORE, "clan_isignore"); + add(STOCKMARKET_GETOFFERTYPE, "stockmarket_getoffertype"); + add(STOCKMARKET_GETOFFERITEM, "stockmarket_getofferitem"); + add(STOCKMARKET_GETOFFERPRICE, "stockmarket_getofferprice"); + add(STOCKMARKET_GETOFFERCOUNT, "stockmarket_getoffercount"); + add(STOCKMARKET_GETOFFERCOMPLETEDCOUNT, "stockmarket_getoffercompletedcount"); + add(STOCKMARKET_GETOFFERCOMPLETEDGOLD, "stockmarket_getoffercompletedgold"); + add(STOCKMARKET_ISOFFEREMPTY, "stockmarket_isofferempty"); + add(STOCKMARKET_ISOFFERSTABLE, "stockmarket_isofferstable"); + add(STOCKMARKET_ISOFFERFINISHED, "stockmarket_isofferfinished"); + add(STOCKMARKET_ISOFFERADDING, "stockmarket_isofferadding"); + add(TRADINGPOST_SORTBY_NAME, "tradingpost_sortby_name"); + add(TRADINGPOST_SORTBY_PRICE, "tradingpost_sortby_price"); + add(TRADINGPOST_SORTFILTERBY_WORLD, "tradingpost_sortfilterby_world"); + add(TRADINGPOST_SORTBY_AGE, "tradingpost_sortby_age"); + add(TRADINGPOST_SORTBY_COUNT, "tradingpost_sortby_count"); + add(TRADINGPOST_GETTOTALOFFERS, "tradingpost_gettotaloffers"); + add(TRADINGPOST_GETOFFERWORLD, "tradingpost_getofferworld"); + add(TRADINGPOST_GETOFFERNAME, "tradingpost_getoffername"); + add(TRADINGPOST_GETOFFERPREVIOUSNAME, "tradingpost_getofferpreviousname"); + add(TRADINGPOST_GETOFFERAGE, "tradingpost_getofferage"); + add(TRADINGPOST_GETOFFERCOUNT, "tradingpost_getoffercount"); + add(TRADINGPOST_GETOFFERPRICE, "tradingpost_getofferprice"); + add(TRADINGPOST_GETOFFERITEM, "tradingpost_getofferitem"); + add(ADD, "add"); + add(SUB, "sub"); + add(MULTIPLY, "multiply"); + add(DIV, "div"); + add(RANDOM, "random"); + add(RANDOMINC, "randominc"); + add(INTERPOLATE, "interpolate"); + add(ADDPERCENT, "addpercent"); + add(SETBIT, "setbit"); + add(CLEARBIT, "clearbit"); + add(TESTBIT, "testbit"); + add(MOD, "mod"); + add(POW, "pow"); + add(INVPOW, "invpow"); + add(AND, "and"); + add(OR, "or"); + add(SCALE, "scale"); + add(APPEND_NUM, "append_num"); + add(APPEND, "append"); + add(APPEND_SIGNNUM, "append_signnum"); + add(LOWERCASE, "lowercase"); + add(FROMDATE, "fromdate"); + add(TEXT_GENDER, "text_gender"); + add(TOSTRING, "tostring"); + add(COMPARE, "compare"); + add(PARAHEIGHT, "paraheight"); + add(PARAWIDTH, "parawidth"); + add(TEXT_SWITCH, "text_switch"); + add(ESCAPE, "escape"); + add(APPEND_CHAR, "append_char"); + add(CHAR_ISPRINTABLE, "char_isprintable"); + add(CHAR_ISALPHANUMERIC, "char_isalphanumeric"); + add(CHAR_ISALPHA, "char_isalpha"); + add(CHAR_ISNUMERIC, "char_isnumeric"); + add(STRING_LENGTH, "string_length"); + add(SUBSTRING, "substring"); + add(REMOVETAGS, "removetags"); + add(STRING_INDEXOF_CHAR, "string_indexof_char"); + add(STRING_INDEXOF_STRING, "string_indexof_string"); + add(UPPERCASE, "uppercase"); + add(OC_NAME, "oc_name"); + add(OC_OP, "oc_op"); + add(OC_IOP, "oc_iop"); + add(OC_COST, "oc_cost"); + add(OC_STACKABLE, "oc_stackable"); + add(OC_CERT, "oc_cert"); + add(OC_UNCERT, "oc_uncert"); + add(OC_MEMBERS, "oc_members"); + add(OC_PLACEHOLDER, "oc_placeholder"); + add(OC_UNPLACEHOLDER, "oc_unplaceholder"); + add(OC_FIND, "oc_find"); + add(OC_FINDNEXT, "oc_findnext"); + add(OC_FINDRESET, "oc_findreset"); + add(CHAT_GETFILTER_PUBLIC, "chat_getfilter_public"); + add(CHAT_SETFILTER, "chat_setfilter"); + add(CHAT_SENDABUSEREPORT, "chat_sendabusereport"); + add(CHAT_GETHISTORY_BYTYPEANDLINE, "chat_gethistory_bytypeandline"); + add(CHAT_GETHISTORY_BYUID, "chat_gethistory_byuid"); + add(CHAT_GETFILTER_PRIVATE, "chat_getfilter_private"); + add(CHAT_SENDPUBLIC, "chat_sendpublic"); + add(CHAT_SENDPRIVATE, "chat_sendprivate"); + add(CHAT_PLAYERNAME, "chat_playername"); + add(CHAT_GETFILTER_TRADE, "chat_getfilter_trade"); + add(CHAT_GETHISTORYLENGTH, "chat_gethistorylength"); + add(CHAT_GETNEXTUID, "chat_getnextuid"); + add(CHAT_GETPREVUID, "chat_getprevuid"); + add(DOCHEAT, "docheat"); + add(CHAT_SETMESSAGEFILTER, "chat_setmessagefilter"); + add(CHAT_GETMESSAGEFILTER, "chat_getmessagefilter"); + add(DEBUGMES, "debugmes"); + add(GETWINDOWMODE, "getwindowmode"); + add(SETWINDOWMODE, "setwindowmode"); + add(GETDEFAULTWINDOWMODE, "getdefaultwindowmode"); + add(SETDEFAULTWINDOWMODE, "setdefaultwindowmode"); + add(CAM_FORCEANGLE, "cam_forceangle"); + add(CAM_GETANGLE_XA, "cam_getangle_xa"); + add(CAM_GETANGLE_YA, "cam_getangle_ya"); + add(CAM_SETFOLLOWHEIGHT, "cam_setfollowheight"); + add(CAM_GETFOLLOWHEIGHT, "cam_getfollowheight"); + add(LOGOUT, "logout"); + add(VIEWPORT_SETFOV, "viewport_setfov"); + add(VIEWPORT_SETZOOM, "viewport_setzoom"); + add(VIEWPORT_CLAMPFOV, "viewport_clampfov"); + add(VIEWPORT_GETEFFECTIVESIZE, "viewport_geteffectivesize"); + add(VIEWPORT_GETZOOM, "viewport_getzoom"); + add(VIEWPORT_GETFOV, "viewport_getfov"); + add(WORLDLIST_FETCH, "worldlist_fetch"); + add(WORLDLIST_START, "worldlist_start"); + add(WORLDLIST_NEXT, "worldlist_next"); + add(WORLDLIST_SPECIFIC, "worldlist_specific"); + add(WORLDLIST_SORT, "worldlist_sort"); + add(GETWORLDINFO, "getworldinfo"); + add(SETFOLLOWEROPSLOWPRIORITY, "setfolloweropslowpriority"); + add(NC_PARAM, "nc_param"); + add(LC_PARAM, "lc_param"); + add(OC_PARAM, "oc_param"); + add(STRUCT_PARAM, "struct_param"); + add(ON_MOBILE, "on_mobile"); + add(CLIENTTYPE, "clienttype"); + add(MOBILE_KEYBOARDHIDE, "mobile_keyboardhide"); + add(BATTERYLEVEL, "batterylevel"); + add(BATTERYCHARGING, "batterycharging"); + add(WIFIAVAILABLE, "wifiavailable"); + add(WORLDMAP_GETMAPNAME, "worldmap_getmapname"); + add(WORLDMAP_SETMAP, "worldmap_setmap"); + add(WORLDMAP_GETZOOM, "worldmap_getzoom"); + add(WORLDMAP_SETZOOM, "worldmap_setzoom"); + add(WORLDMAP_ISLOADED, "worldmap_isloaded"); + add(WORLDMAP_JUMPTODISPLAYCOORD, "worldmap_jumptodisplaycoord"); + add(WORLDMAP_JUMPTODISPLAYCOORD_INSTANT, "worldmap_jumptodisplaycoord_instant"); + add(WORLDMAP_JUMPTOSOURCECOORD, "worldmap_jumptosourcecoord"); + add(WORLDMAP_JUMPTOSOURCECOORD_INSTANT, "worldmap_jumptosourcecoord_instant"); + add(WORLDMAP_GETDISPLAYPOSITION, "worldmap_getdisplayposition"); + add(WORLDMAP_GETCONFIGORIGIN, "worldmap_getconfigorigin"); + add(WORLDMAP_GETCONFIGSIZE, "worldmap_getconfigsize"); + add(WORLDMAP_GETCONFIGBOUNDS, "worldmap_getconfigbounds"); + add(WORLDMAP_GETCONFIGZOOM, "worldmap_getconfigzoom"); + add(WORLDMAP_GETCURRENTMAP, "worldmap_getcurrentmap"); + add(WORLDMAP_GETDISPLAYCOORD, "worldmap_getdisplaycoord"); + add(WORLDMAP_COORDINMAP, "worldmap_coordinmap"); + add(WORLDMAP_GETSIZE, "worldmap_getsize"); + add(WORLDMAP_PERPETUALFLASH, "worldmap_perpetualflash"); + add(WORLDMAP_FLASHELEMENT, "worldmap_flashelement"); + add(WORLDMAP_FLASHELEMENTCATEGORY, "worldmap_flashelementcategory"); + add(WORLDMAP_STOPCURRENTFLASHES, "worldmap_stopcurrentflashes"); + add(WORLDMAP_DISABLEELEMENTS, "worldmap_disableelements"); + add(WORLDMAP_DISABLEELEMENT, "worldmap_disableelement"); + add(WORLDMAP_DISABLEELEMENTCATEGORY, "worldmap_disableelementcategory"); + add(WORLDMAP_GETDISABLEELEMENTS, "worldmap_getdisableelements"); + add(WORLDMAP_GETDISABLEELEMENT, "worldmap_getdisableelement"); + add(WORLDMAP_GETDISABLEELEMENTCATEGORY, "worldmap_getdisableelementcategory"); + add(WORLDMAP_LISTELEMENT_START, "worldmap_listelement_start"); + add(WORLDMAP_LISTELEMENT_NEXT, "worldmap_listelement_next"); + add(MEC_TEXT, "mec_text"); + add(MEC_TEXTSIZE, "mec_textsize"); + add(MEC_CATEGORY, "mec_category"); + add(MEC_SPRITE, "mec_sprite"); + add(WORLDMAP_ELEMENT, "worldmap_element"); + add(WORLDMAP_ELEMENTCOORD, "worldmap_elementcoord"); + } + + protected void add(int opcode, String name) + { + Instruction i = new Instruction(opcode); + i.setName(name); + + assert instructions.containsKey(opcode) == false; + instructions.put(opcode, i); + + if (name != null) + { + assert instructionsByName.containsKey(name) == false; + instructionsByName.put(name, i); + } + } + + public Instruction find(int opcode) + { + return instructions.get(opcode); + } + + public Instruction find(String name) + { + return instructionsByName.get(name); + } +} diff --git a/src/main/java/net/runelite/cache/script/Opcodes.java b/src/main/java/net/runelite/cache/script/Opcodes.java new file mode 100644 index 0000000..95dd243 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/Opcodes.java @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2017, Adam + * Copyright (c) 2018-2019, Hunter WB + * Copyright (c) 2019, Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.script; + +public class Opcodes +{ + public static final int ICONST = 0; + public static final int GET_VARP = 1; + public static final int SET_VARP = 2; + public static final int SCONST = 3; + public static final int JUMP = 6; + public static final int IF_ICMPNE = 7; + public static final int IF_ICMPEQ = 8; + public static final int IF_ICMPLT = 9; + public static final int IF_ICMPGT = 10; + public static final int RETURN = 21; + public static final int GET_VARBIT = 25; + public static final int SET_VARBIT = 27; + public static final int IF_ICMPLE = 31; + public static final int IF_ICMPGE = 32; + public static final int ILOAD = 33; + public static final int ISTORE = 34; + public static final int SLOAD = 35; + public static final int SSTORE = 36; + public static final int JOIN_STRING = 37; + public static final int POP_INT = 38; + public static final int POP_STRING = 39; + public static final int INVOKE = 40; + public static final int GET_VARC_INT = 42; + public static final int SET_VARC_INT = 43; + public static final int DEFINE_ARRAY = 44; + public static final int GET_ARRAY_INT = 45; + public static final int SET_ARRAY_INT = 46; + public static final int GET_VARC_STRING_OLD = 47; + public static final int SET_VARC_STRING_OLD = 48; + public static final int GET_VARC_STRING = 49; + public static final int SET_VARC_STRING = 50; + public static final int SWITCH = 60; + public static final int CC_CREATE = 100; + public static final int CC_DELETE = 101; + public static final int CC_DELETEALL = 102; + public static final int CC_FIND = 200; + public static final int IF_FIND = 201; + public static final int CC_SETPOSITION = 1000; + public static final int CC_SETSIZE = 1001; + public static final int CC_SETHIDE = 1003; + public static final int CC_SETNOCLICKTHROUGH = 1005; + public static final int CC_SETNOSCROLLTHROUGH = 1006; + public static final int CC_SETSCROLLPOS = 1100; + public static final int CC_SETCOLOUR = 1101; + public static final int CC_SETFILL = 1102; + public static final int CC_SETTRANS = 1103; + public static final int CC_SETLINEWID = 1104; + public static final int CC_SETGRAPHIC = 1105; + public static final int CC_SET2DANGLE = 1106; + public static final int CC_SETTILING = 1107; + public static final int CC_SETMODEL = 1108; + public static final int CC_SETMODELANGLE = 1109; + public static final int CC_SETMODELANIM = 1110; + public static final int CC_SETMODELORTHOG = 1111; + public static final int CC_SETTEXT = 1112; + public static final int CC_SETTEXTFONT = 1113; + public static final int CC_SETTEXTALIGN = 1114; + public static final int CC_SETTEXTSHADOW = 1115; + public static final int CC_SETOUTLINE = 1116; + public static final int CC_SETGRAPHICSHADOW = 1117; + public static final int CC_SETVFLIP = 1118; + public static final int CC_SETHFLIP = 1119; + public static final int CC_SETSCROLLSIZE = 1120; + public static final int CC_RESUME_PAUSEBUTTON = 1121; + public static final int CC_SETFILLCOLOUR = 1123; + public static final int CC_SETLINEDIRECTION = 1126; + public static final int CC_SETMODELTRANSPARENT = 1127; + public static final int CC_SETOBJECT = 1200; + public static final int CC_SETNPCHEAD = 1201; + public static final int CC_SETPLAYERHEAD_SELF = 1202; + public static final int CC_SETOBJECT_NONUM = 1205; + public static final int CC_SETOBJECT_ALWAYS_NUM = 1212; + public static final int CC_SETOP = 1300; + public static final int CC_SETDRAGGABLE = 1301; + public static final int CC_SETDRAGGABLEBEHAVIOR = 1302; + public static final int CC_SETDRAGDEADZONE = 1303; + public static final int CC_SETDRAGDEADTIME = 1304; + public static final int CC_SETOPBASE = 1305; + public static final int CC_SETTARGETVERB = 1306; + public static final int CC_CLEAROPS = 1307; + public static final int CC_SETOPKEY = 1350; + public static final int CC_SETOPTKEY = 1351; + public static final int CC_SETOPKEYRATE = 1352; + public static final int CC_SETOPTKEYRATE = 1353; + public static final int CC_SETOPKEYIGNOREHELD = 1354; + public static final int CC_SETOPTKEYIGNOREHELD = 1355; + public static final int CC_SETONCLICK = 1400; + public static final int CC_SETONHOLD = 1401; + public static final int CC_SETONRELEASE = 1402; + public static final int CC_SETONMOUSEOVER = 1403; + public static final int CC_SETONMOUSELEAVE = 1404; + public static final int CC_SETONDRAG = 1405; + public static final int CC_SETONTARGETLEAVE = 1406; + public static final int CC_SETONVARTRANSMIT = 1407; + public static final int CC_SETONTIMER = 1408; + public static final int CC_SETONOP = 1409; + public static final int CC_SETONDRAGCOMPLETE = 1410; + public static final int CC_SETONCLICKREPEAT = 1411; + public static final int CC_SETONMOUSEREPEAT = 1412; + public static final int CC_SETONINVTRANSMIT = 1414; + public static final int CC_SETONSTATTRANSMIT = 1415; + public static final int CC_SETONTARGETENTER = 1416; + public static final int CC_SETONSCROLLWHEEL = 1417; + public static final int CC_SETONCHATTRANSMIT = 1418; + public static final int CC_SETONKEY = 1419; + public static final int CC_SETONFRIENDTRANSMIT = 1420; + public static final int CC_SETONCLANTRANSMIT = 1421; + public static final int CC_SETONMISCTRANSMIT = 1422; + public static final int CC_SETONDIALOGABORT = 1423; + public static final int CC_SETONSUBCHANGE = 1424; + public static final int CC_SETONSTOCKTRANSMIT = 1425; + public static final int CC_SETONRESIZE = 1427; + public static final int CC_GETX = 1500; + public static final int CC_GETY = 1501; + public static final int CC_GETWIDTH = 1502; + public static final int CC_GETHEIGHT = 1503; + public static final int CC_GETHIDE = 1504; + public static final int CC_GETLAYER = 1505; + public static final int CC_GETSCROLLX = 1600; + public static final int CC_GETSCROLLY = 1601; + public static final int CC_GETTEXT = 1602; + public static final int CC_GETSCROLLWIDTH = 1603; + public static final int CC_GETSCROLLHEIGHT = 1604; + public static final int CC_GETMODELZOOM = 1605; + public static final int CC_GETMODELANGLE_X = 1606; + public static final int CC_GETMODELANGLE_Z = 1607; + public static final int CC_GETMODELANGLE_Y = 1608; + public static final int CC_GETTRANS = 1609; + public static final int CC_GETCOLOUR = 1611; + public static final int CC_GETFILLCOLOUR = 1612; + public static final int CC_GETMODELTRANSPARENT = 1614; + public static final int CC_GETINVOBJECT = 1700; + public static final int CC_GETINVCOUNT = 1701; + public static final int CC_GETID = 1702; + public static final int CC_GETTARGETMASK = 1800; + public static final int CC_GETOP = 1801; + public static final int CC_GETOPBASE = 1802; + public static final int CC_CALLONRESIZE = 1927; + public static final int IF_SETPOSITION = 2000; + public static final int IF_SETSIZE = 2001; + public static final int IF_SETHIDE = 2003; + public static final int IF_SETNOCLICKTHROUGH = 2005; + public static final int IF_SETSCROLLPOS = 2100; + public static final int IF_SETCOLOUR = 2101; + public static final int IF_SETFILL = 2102; + public static final int IF_SETTRANS = 2103; + public static final int IF_SETLINEWID = 2104; + public static final int IF_SETGRAPHIC = 2105; + public static final int IF_SET2DANGLE = 2106; + public static final int IF_SETTILING = 2107; + public static final int IF_SETMODEL = 2108; + public static final int IF_SETMODELANGLE = 2109; + public static final int IF_SETMODELANIM = 2110; + public static final int IF_SETMODELORTHOG = 2111; + public static final int IF_SETTEXT = 2112; + public static final int IF_SETTEXTFONT = 2113; + public static final int IF_SETTEXTALIGN = 2114; + public static final int IF_SETTEXTSHADOW = 2115; + public static final int IF_SETOUTLINE = 2116; + public static final int IF_SETGRAPHICSHADOW = 2117; + public static final int IF_SETVFLIP = 2118; + public static final int IF_SETHFLIP = 2119; + public static final int IF_SETSCROLLSIZE = 2120; + public static final int IF_RESUME_PAUSEBUTTON = 2121; + public static final int IF_SETFILLCOLOUR = 2123; + public static final int IF_SETLINEDIRECTION = 2126; + public static final int IF_SETMODELTRANSPARENT = 2127; + public static final int IF_SETOBJECT = 2200; + public static final int IF_SETNPCHEAD = 2201; + public static final int IF_SETPLAYERHEAD_SELF = 2202; + public static final int IF_SETOBJECT_NONUM = 2205; + public static final int IF_SETOBJECT_ALWAYS_NUM = 2212; + public static final int IF_SETOP = 2300; + public static final int IF_SETDRAGGABLE = 2301; + public static final int IF_SETDRAGGABLEBEHAVIOR = 2302; + public static final int IF_SETDRAGDEADZONE = 2303; + public static final int IF_SETDRAGDEADTIME = 2304; + public static final int IF_SETOPBASE = 2305; + public static final int IF_SETTARGETVERB = 2306; + public static final int IF_CLEAROPS = 2307; + public static final int IF_SETOPKEY = 2350; + public static final int IF_SETOPTKEY = 2351; + public static final int IF_SETOPKEYRATE = 2352; + public static final int IF_SETOPTKEYRATE = 2353; + public static final int IF_SETOPKEYIGNOREHELD = 2354; + public static final int IF_SETOPTKEYIGNOREHELD = 2355; + public static final int IF_SETONCLICK = 2400; + public static final int IF_SETONHOLD = 2401; + public static final int IF_SETONRELEASE = 2402; + public static final int IF_SETONMOUSEOVER = 2403; + public static final int IF_SETONMOUSELEAVE = 2404; + public static final int IF_SETONDRAG = 2405; + public static final int IF_SETONTARGETLEAVE = 2406; + public static final int IF_SETONVARTRANSMIT = 2407; + public static final int IF_SETONTIMER = 2408; + public static final int IF_SETONOP = 2409; + public static final int IF_SETONDRAGCOMPLETE = 2410; + public static final int IF_SETONCLICKREPEAT = 2411; + public static final int IF_SETONMOUSEREPEAT = 2412; + public static final int IF_SETONINVTRANSMIT = 2414; + public static final int IF_SETONSTATTRANSMIT = 2415; + public static final int IF_SETONTARGETENTER = 2416; + public static final int IF_SETONSCROLLWHEEL = 2417; + public static final int IF_SETONCHATTRANSMIT = 2418; + public static final int IF_SETONKEY = 2419; + public static final int IF_SETONFRIENDTRANSMIT = 2420; + public static final int IF_SETONCLANTRANSMIT = 2421; + public static final int IF_SETONMISCTRANSMIT = 2422; + public static final int IF_SETONDIALOGABORT = 2423; + public static final int IF_SETONSUBCHANGE = 2424; + public static final int IF_SETONSTOCKTRANSMIT = 2425; + public static final int IF_SETONRESIZE = 2427; + public static final int IF_GETX = 2500; + public static final int IF_GETY = 2501; + public static final int IF_GETWIDTH = 2502; + public static final int IF_GETHEIGHT = 2503; + public static final int IF_GETHIDE = 2504; + public static final int IF_GETLAYER = 2505; + public static final int IF_GETSCROLLX = 2600; + public static final int IF_GETSCROLLY = 2601; + public static final int IF_GETTEXT = 2602; + public static final int IF_GETSCROLLWIDTH = 2603; + public static final int IF_GETSCROLLHEIGHT = 2604; + public static final int IF_GETMODELZOOM = 2605; + public static final int IF_GETMODELANGLE_X = 2606; + public static final int IF_GETMODELANGLE_Z = 2607; + public static final int IF_GETMODELANGLE_Y = 2608; + public static final int IF_GETTRANS = 2609; + public static final int IF_GETCOLOUR = 2611; + public static final int IF_GETFILLCOLOUR = 2612; + public static final int IF_GETMODELTRANSPARENT = 2614; + public static final int IF_GETINVOBJECT = 2700; + public static final int IF_GETINVCOUNT = 2701; + public static final int IF_HASSUB = 2702; + public static final int IF_GETTOP = 2706; + public static final int IF_GETTARGETMASK = 2800; + public static final int IF_GETOP = 2801; + public static final int IF_GETOPBASE = 2802; + public static final int IF_CALLONRESIZE = 2927; + public static final int MES = 3100; + public static final int ANIM = 3101; + public static final int IF_CLOSE = 3103; + public static final int RESUME_COUNTDIALOG = 3104; + public static final int RESUME_NAMEDIALOG = 3105; + public static final int RESUME_STRINGDIALOG = 3106; + public static final int OPPLAYER = 3107; + public static final int IF_DRAGPICKUP = 3108; + public static final int CC_DRAGPICKUP = 3109; + public static final int MOUSECAM = 3110; + public static final int GETREMOVEROOFS = 3111; + public static final int SETREMOVEROOFS = 3112; + public static final int OPENURL = 3113; + public static final int RESUME_OBJDIALOG = 3115; + public static final int BUG_REPORT = 3116; + public static final int SETSHIFTCLICKDROP = 3117; + public static final int SETSHOWMOUSEOVERTEXT = 3118; + public static final int RENDERSELF = 3119; + public static final int SETSHOWMOUSECROSS = 3125; + public static final int SETSHOWLOADINGMESSAGES = 3126; + public static final int SETTAPTODROP = 3127; + public static final int GETTAPTODROP = 3128; + public static final int SETOCULUSORBSPEED = 3129; + public static final int GETCANVASSIZE = 3132; + public static final int MOBILE_SETFPS = 3133; + public static final int MOBILE_OPENSTORE = 3134; + public static final int MOBILE_OPENSTORECATEGORY = 3135; + public static final int SETHIDEUSERNAME = 3141; + public static final int GETHIDEUSERNAME = 3142; + public static final int SETREMEMBERUSERNAME = 3143; + public static final int GETREMEMBERUSERNAME = 3144; + public static final int SETTITLEMUSICENABLED = 3146; + public static final int GETTITLEMUSICENABLED = 3147; + public static final int SOUND_SYNTH = 3200; + public static final int SOUND_SONG = 3201; + public static final int SOUND_JINGLE = 3202; + public static final int CLIENTCLOCK = 3300; + public static final int INV_GETOBJ = 3301; + public static final int INV_GETNUM = 3302; + public static final int INV_TOTAL = 3303; + public static final int INV_SIZE = 3304; + public static final int STAT = 3305; + public static final int STAT_BASE = 3306; + public static final int STAT_XP = 3307; + public static final int COORD = 3308; + public static final int COORDX = 3309; + public static final int COORDZ = 3310; + public static final int COORDY = 3311; + public static final int MAP_MEMBERS = 3312; + public static final int INVOTHER_GETOBJ = 3313; + public static final int INVOTHER_GETNUM = 3314; + public static final int INVOTHER_TOTAL = 3315; + public static final int STAFFMODLEVEL = 3316; + public static final int REBOOTTIMER = 3317; + public static final int MAP_WORLD = 3318; + public static final int RUNENERGY_VISIBLE = 3321; + public static final int RUNWEIGHT_VISIBLE = 3322; + public static final int PLAYERMOD = 3323; + public static final int WORLDFLAGS = 3324; + public static final int MOVECOORD = 3325; + public static final int ENUM_STRING = 3400; + public static final int ENUM = 3408; + public static final int ENUM_GETOUTPUTCOUNT = 3411; + public static final int FRIEND_COUNT = 3600; + public static final int FRIEND_GETNAME = 3601; + public static final int FRIEND_GETWORLD = 3602; + public static final int FRIEND_GETRANK = 3603; + public static final int FRIEND_SETRANK = 3604; + public static final int FRIEND_ADD = 3605; + public static final int FRIEND_DEL = 3606; + public static final int IGNORE_ADD = 3607; + public static final int IGNORE_DEL = 3608; + public static final int FRIEND_TEST = 3609; + public static final int CLAN_GETCHATDISPLAYNAME = 3611; + public static final int CLAN_GETCHATCOUNT = 3612; + public static final int CLAN_GETCHATUSERNAME = 3613; + public static final int CLAN_GETCHATUSERWORLD = 3614; + public static final int CLAN_GETCHATUSERRANK = 3615; + public static final int CLAN_GETCHATMINKICK = 3616; + public static final int CLAN_KICKUSER = 3617; + public static final int CLAN_GETCHATRANK = 3618; + public static final int CLAN_JOINCHAT = 3619; + public static final int CLAN_LEAVECHAT = 3620; + public static final int IGNORE_COUNT = 3621; + public static final int IGNORE_GETNAME = 3622; + public static final int IGNORE_TEST = 3623; + public static final int CLAN_ISSELF = 3624; + public static final int CLAN_GETCHATOWNERNAME = 3625; + public static final int CLAN_ISFRIEND = 3626; + public static final int CLAN_ISIGNORE = 3627; + public static final int STOCKMARKET_GETOFFERTYPE = 3903; + public static final int STOCKMARKET_GETOFFERITEM = 3904; + public static final int STOCKMARKET_GETOFFERPRICE = 3905; + public static final int STOCKMARKET_GETOFFERCOUNT = 3906; + public static final int STOCKMARKET_GETOFFERCOMPLETEDCOUNT = 3907; + public static final int STOCKMARKET_GETOFFERCOMPLETEDGOLD = 3908; + public static final int STOCKMARKET_ISOFFEREMPTY = 3910; + public static final int STOCKMARKET_ISOFFERSTABLE = 3911; + public static final int STOCKMARKET_ISOFFERFINISHED = 3912; + public static final int STOCKMARKET_ISOFFERADDING = 3913; + public static final int TRADINGPOST_SORTBY_NAME = 3914; + public static final int TRADINGPOST_SORTBY_PRICE = 3915; + public static final int TRADINGPOST_SORTFILTERBY_WORLD = 3916; + public static final int TRADINGPOST_SORTBY_AGE = 3917; + public static final int TRADINGPOST_SORTBY_COUNT = 3918; + public static final int TRADINGPOST_GETTOTALOFFERS = 3919; + public static final int TRADINGPOST_GETOFFERWORLD = 3920; + public static final int TRADINGPOST_GETOFFERNAME = 3921; + public static final int TRADINGPOST_GETOFFERPREVIOUSNAME = 3922; + public static final int TRADINGPOST_GETOFFERAGE = 3923; + public static final int TRADINGPOST_GETOFFERCOUNT = 3924; + public static final int TRADINGPOST_GETOFFERPRICE = 3925; + public static final int TRADINGPOST_GETOFFERITEM = 3926; + public static final int ADD = 4000; + public static final int SUB = 4001; + public static final int MULTIPLY = 4002; + public static final int DIV = 4003; + public static final int RANDOM = 4004; + public static final int RANDOMINC = 4005; + public static final int INTERPOLATE = 4006; + public static final int ADDPERCENT = 4007; + public static final int SETBIT = 4008; + public static final int CLEARBIT = 4009; + public static final int TESTBIT = 4010; + public static final int MOD = 4011; + public static final int POW = 4012; + public static final int INVPOW = 4013; + public static final int AND = 4014; + public static final int OR = 4015; + public static final int SCALE = 4018; + public static final int APPEND_NUM = 4100; + public static final int APPEND = 4101; + public static final int APPEND_SIGNNUM = 4102; + public static final int LOWERCASE = 4103; + public static final int FROMDATE = 4104; + public static final int TEXT_GENDER = 4105; + public static final int TOSTRING = 4106; + public static final int COMPARE = 4107; + public static final int PARAHEIGHT = 4108; + public static final int PARAWIDTH = 4109; + public static final int TEXT_SWITCH = 4110; + public static final int ESCAPE = 4111; + public static final int APPEND_CHAR = 4112; + public static final int CHAR_ISPRINTABLE = 4113; + public static final int CHAR_ISALPHANUMERIC = 4114; + public static final int CHAR_ISALPHA = 4115; + public static final int CHAR_ISNUMERIC = 4116; + public static final int STRING_LENGTH = 4117; + public static final int SUBSTRING = 4118; + public static final int REMOVETAGS = 4119; + public static final int STRING_INDEXOF_CHAR = 4120; + public static final int STRING_INDEXOF_STRING = 4121; + public static final int UPPERCASE = 4122; + public static final int OC_NAME = 4200; + public static final int OC_OP = 4201; + public static final int OC_IOP = 4202; + public static final int OC_COST = 4203; + public static final int OC_STACKABLE = 4204; + public static final int OC_CERT = 4205; + public static final int OC_UNCERT = 4206; + public static final int OC_MEMBERS = 4207; + public static final int OC_PLACEHOLDER = 4208; + public static final int OC_UNPLACEHOLDER = 4209; + public static final int OC_FIND = 4210; + public static final int OC_FINDNEXT = 4211; + public static final int OC_FINDRESET = 4212; + public static final int CHAT_GETFILTER_PUBLIC = 5000; + public static final int CHAT_SETFILTER = 5001; + public static final int CHAT_SENDABUSEREPORT = 5002; + public static final int CHAT_GETHISTORY_BYTYPEANDLINE = 5003; + public static final int CHAT_GETHISTORY_BYUID = 5004; + public static final int CHAT_GETFILTER_PRIVATE = 5005; + public static final int CHAT_SENDPUBLIC = 5008; + public static final int CHAT_SENDPRIVATE = 5009; + public static final int CHAT_PLAYERNAME = 5015; + public static final int CHAT_GETFILTER_TRADE = 5016; + public static final int CHAT_GETHISTORYLENGTH = 5017; + public static final int CHAT_GETNEXTUID = 5018; + public static final int CHAT_GETPREVUID = 5019; + public static final int DOCHEAT = 5020; + public static final int CHAT_SETMESSAGEFILTER = 5021; + public static final int CHAT_GETMESSAGEFILTER = 5022; + public static final int DEBUGMES = 5023; + public static final int GETWINDOWMODE = 5306; + public static final int SETWINDOWMODE = 5307; + public static final int GETDEFAULTWINDOWMODE = 5308; + public static final int SETDEFAULTWINDOWMODE = 5309; + public static final int CAM_FORCEANGLE = 5504; + public static final int CAM_GETANGLE_XA = 5505; + public static final int CAM_GETANGLE_YA = 5506; + public static final int CAM_SETFOLLOWHEIGHT = 5530; + public static final int CAM_GETFOLLOWHEIGHT = 5531; + public static final int LOGOUT = 5630; + public static final int VIEWPORT_SETFOV = 6200; + public static final int VIEWPORT_SETZOOM = 6201; + public static final int VIEWPORT_CLAMPFOV = 6202; + public static final int VIEWPORT_GETEFFECTIVESIZE = 6203; + public static final int VIEWPORT_GETZOOM = 6204; + public static final int VIEWPORT_GETFOV = 6205; + public static final int WORLDLIST_FETCH = 6500; + public static final int WORLDLIST_START = 6501; + public static final int WORLDLIST_NEXT = 6502; + public static final int WORLDLIST_SPECIFIC = 6506; + public static final int WORLDLIST_SORT = 6507; + public static final int GETWORLDINFO = 6511; + public static final int SETFOLLOWEROPSLOWPRIORITY = 6512; + public static final int NC_PARAM = 6513; + public static final int LC_PARAM = 6514; + public static final int OC_PARAM = 6515; + public static final int STRUCT_PARAM = 6516; + public static final int ON_MOBILE = 6518; + public static final int CLIENTTYPE = 6519; + public static final int MOBILE_KEYBOARDHIDE = 6521; + public static final int BATTERYLEVEL = 6524; + public static final int BATTERYCHARGING = 6525; + public static final int WIFIAVAILABLE = 6526; + public static final int WORLDMAP_GETMAPNAME = 6601; + public static final int WORLDMAP_SETMAP = 6602; + public static final int WORLDMAP_GETZOOM = 6603; + public static final int WORLDMAP_SETZOOM = 6604; + public static final int WORLDMAP_ISLOADED = 6605; + public static final int WORLDMAP_JUMPTODISPLAYCOORD = 6606; + public static final int WORLDMAP_JUMPTODISPLAYCOORD_INSTANT = 6607; + public static final int WORLDMAP_JUMPTOSOURCECOORD = 6608; + public static final int WORLDMAP_JUMPTOSOURCECOORD_INSTANT = 6609; + public static final int WORLDMAP_GETDISPLAYPOSITION = 6610; + public static final int WORLDMAP_GETCONFIGORIGIN = 6611; + public static final int WORLDMAP_GETCONFIGSIZE = 6612; + public static final int WORLDMAP_GETCONFIGBOUNDS = 6613; + public static final int WORLDMAP_GETCONFIGZOOM = 6614; + public static final int WORLDMAP_GETCURRENTMAP = 6616; + public static final int WORLDMAP_GETDISPLAYCOORD = 6617; + public static final int WORLDMAP_COORDINMAP = 6621; + public static final int WORLDMAP_GETSIZE = 6622; + public static final int WORLDMAP_PERPETUALFLASH = 6628; + public static final int WORLDMAP_FLASHELEMENT = 6629; + public static final int WORLDMAP_FLASHELEMENTCATEGORY = 6630; + public static final int WORLDMAP_STOPCURRENTFLASHES = 6631; + public static final int WORLDMAP_DISABLEELEMENTS = 6632; + public static final int WORLDMAP_DISABLEELEMENT = 6633; + public static final int WORLDMAP_DISABLEELEMENTCATEGORY = 6634; + public static final int WORLDMAP_GETDISABLEELEMENTS = 6635; + public static final int WORLDMAP_GETDISABLEELEMENT = 6636; + public static final int WORLDMAP_GETDISABLEELEMENTCATEGORY = 6637; + public static final int WORLDMAP_LISTELEMENT_START = 6639; + public static final int WORLDMAP_LISTELEMENT_NEXT = 6640; + public static final int MEC_TEXT = 6693; + public static final int MEC_TEXTSIZE = 6694; + public static final int MEC_CATEGORY = 6695; + public static final int MEC_SPRITE = 6696; + public static final int WORLDMAP_ELEMENT = 6697; + public static final int WORLDMAP_ELEMENTCOORD = 6699; +} diff --git a/src/main/java/net/runelite/cache/script/assembler/Assembler.java b/src/main/java/net/runelite/cache/script/assembler/Assembler.java new file mode 100644 index 0000000..85c37c4 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/assembler/Assembler.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.script.assembler; + +import java.io.IOException; +import java.io.InputStream; +import net.runelite.cache.definitions.ScriptDefinition; +import net.runelite.cache.script.Instructions; +import net.runelite.cache.script.assembler.rs2asmParser.ProgContext; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTreeWalker; + +public class Assembler +{ + private final Instructions instructions; + + public Assembler(Instructions instructions) + { + this.instructions = instructions; + } + + public ScriptDefinition assemble(InputStream in) throws IOException + { + // Get our lexer + rs2asmLexer lexer = new rs2asmLexer(CharStreams.fromStream(in)); + + LexerErrorListener errorListener = new LexerErrorListener(); + lexer.addErrorListener(errorListener); + + // Get a list of matched tokens + CommonTokenStream tokens = new CommonTokenStream(lexer); + + // Pass the tokens to the parser + rs2asmParser parser = new rs2asmParser(tokens); + + // Specify our entry point + ProgContext progContext = parser.prog(); + + if (errorListener.getErrors() > 0) + { + throw new RuntimeException("syntax error"); + } + + // Walk it and attach our listener + ParseTreeWalker walker = new ParseTreeWalker(); + + // walk through first and resolve labels + LabelVisitor labelVisitor = new LabelVisitor(); + walker.walk(labelVisitor, progContext); + + ScriptWriter listener = new ScriptWriter(instructions, labelVisitor); + walker.walk(listener, progContext); + + return listener.buildScript(); + } +} diff --git a/src/main/java/net/runelite/cache/script/assembler/LabelVisitor.java b/src/main/java/net/runelite/cache/script/assembler/LabelVisitor.java new file mode 100644 index 0000000..b78cfd6 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/assembler/LabelVisitor.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.script.assembler; + +import java.util.HashMap; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LabelVisitor extends rs2asmBaseListener +{ + private static final Logger logger = LoggerFactory.getLogger(LabelVisitor.class); + + private int pos; + private final Map map = new HashMap<>(); + + @Override + public void exitInstruction(rs2asmParser.InstructionContext ctx) + { + ++pos; + } + + @Override + public void enterLabel(rs2asmParser.LabelContext ctx) + { + String text = ctx.getText(); + text = text.substring(0, text.length() - 1); // remove trailing : + + logger.debug("Label {} is on instruction {}", text, pos); + + map.put(text, pos); + } + + public Integer getInstructionForLabel(String label) + { + return map.get(label); + } +} diff --git a/src/main/java/net/runelite/cache/script/assembler/LexerErrorListener.java b/src/main/java/net/runelite/cache/script/assembler/LexerErrorListener.java new file mode 100644 index 0000000..bd3463a --- /dev/null +++ b/src/main/java/net/runelite/cache/script/assembler/LexerErrorListener.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.script.assembler; + +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; + +public class LexerErrorListener extends BaseErrorListener +{ + private int errors; + + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) + { + ++errors; + } + + public int getErrors() + { + return errors; + } + +} diff --git a/src/main/java/net/runelite/cache/script/assembler/LookupCase.java b/src/main/java/net/runelite/cache/script/assembler/LookupCase.java new file mode 100644 index 0000000..8c97fee --- /dev/null +++ b/src/main/java/net/runelite/cache/script/assembler/LookupCase.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.script.assembler; + +public class LookupCase +{ + private int value; + private int offset; + + public int getValue() + { + return value; + } + + public void setValue(int value) + { + this.value = value; + } + + public int getOffset() + { + return offset; + } + + public void setOffset(int offset) + { + this.offset = offset; + } +} diff --git a/src/main/java/net/runelite/cache/script/assembler/LookupSwitch.java b/src/main/java/net/runelite/cache/script/assembler/LookupSwitch.java new file mode 100644 index 0000000..e1d305d --- /dev/null +++ b/src/main/java/net/runelite/cache/script/assembler/LookupSwitch.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.script.assembler; + +import java.util.ArrayList; +import java.util.List; + +public class LookupSwitch +{ + private final List cases = new ArrayList<>(); + + public List getCases() + { + return cases; + } +} diff --git a/src/main/java/net/runelite/cache/script/assembler/ScriptWriter.java b/src/main/java/net/runelite/cache/script/assembler/ScriptWriter.java new file mode 100644 index 0000000..60ebfb3 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/assembler/ScriptWriter.java @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.script.assembler; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import net.runelite.cache.definitions.ScriptDefinition; +import net.runelite.cache.script.Instruction; +import net.runelite.cache.script.Instructions; +import net.runelite.cache.script.Opcodes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ScriptWriter extends rs2asmBaseListener +{ + private static final Logger logger = LoggerFactory.getLogger(ScriptWriter.class); + + private final Instructions instructions; + private final LabelVisitor labelVisitor; + + private int id; + private int pos; + private int intStackCount; + private int stringStackCount; + private int localIntCount; + private int localStringCount; + private List opcodes = new ArrayList<>(); + private List iops = new ArrayList<>(); + private List sops = new ArrayList<>(); + private List switches = new ArrayList<>(); + + public ScriptWriter(Instructions instructions, LabelVisitor labelVisitor) + { + this.instructions = instructions; + this.labelVisitor = labelVisitor; + } + + @Override + public void enterId_value(rs2asmParser.Id_valueContext ctx) + { + int value = Integer.parseInt(ctx.getText()); + id = value; + } + + @Override + public void enterInt_stack_value(rs2asmParser.Int_stack_valueContext ctx) + { + int value = Integer.parseInt(ctx.getText()); + intStackCount = value; + } + + @Override + public void enterString_stack_value(rs2asmParser.String_stack_valueContext ctx) + { + int value = Integer.parseInt(ctx.getText()); + stringStackCount = value; + } + + @Override + public void enterInt_var_value(rs2asmParser.Int_var_valueContext ctx) + { + int value = Integer.parseInt(ctx.getText()); + localIntCount = value; + } + + @Override + public void enterString_var_value(rs2asmParser.String_var_valueContext ctx) + { + int value = Integer.parseInt(ctx.getText()); + localStringCount = value; + } + + @Override + public void exitInstruction(rs2asmParser.InstructionContext ctx) + { + ++pos; + } + + @Override + public void enterName_string(rs2asmParser.Name_stringContext ctx) + { + String text = ctx.getText(); + Instruction i = instructions.find(text); + if (i == null) + { + logger.warn("Unknown instruction {}", text); + throw new RuntimeException("Unknown instruction " + text); + } + + int opcode = i.getOpcode(); + addOpcode(opcode); + } + + @Override + public void enterName_opcode(rs2asmParser.Name_opcodeContext ctx) + { + String text = ctx.getText(); + int opcode = Integer.parseInt(text); + addOpcode(opcode); + } + + private void addOpcode(int opcode) + { + assert opcodes.size() == pos; + assert iops.size() == pos; + assert sops.size() == pos; + assert switches.size() == pos; + + opcodes.add(opcode); + iops.add(null); + sops.add(null); + switches.add(null); + } + + @Override + public void enterOperand_int(rs2asmParser.Operand_intContext ctx) + { + String text = ctx.getText(); + int value = Integer.parseInt(text); + iops.set(pos, value); + } + + @Override + public void enterOperand_qstring(rs2asmParser.Operand_qstringContext ctx) + { + String text = ctx.getText(); + text = text.substring(1, text.length() - 1); + sops.set(pos, text); + } + + @Override + public void enterOperand_label(rs2asmParser.Operand_labelContext ctx) + { + String text = ctx.getText(); + Integer instruction = labelVisitor.getInstructionForLabel(text); + if (instruction == null) + { + throw new RuntimeException("reference to unknown label " + text); + } + + int target = instruction - pos - 1; // -1 to go to the instruction prior + iops.set(pos, target); + } + + @Override + public void enterSwitch_lookup(rs2asmParser.Switch_lookupContext ctx) + { + if (switches.get(pos - 1) != null) + { + return; + } + + LookupSwitch ls = new LookupSwitch(); + switches.set(pos - 1, ls); + } + + @Override + public void exitSwitch_key(rs2asmParser.Switch_keyContext ctx) + { + String text = ctx.getText(); + int key = Integer.parseInt(text); + + LookupSwitch ls = switches.get(pos - 1); + assert ls != null; + + LookupCase scase = new LookupCase(); + scase.setValue(key); + + ls.getCases().add(scase); + } + + @Override + public void exitSwitch_value(rs2asmParser.Switch_valueContext ctx) + { + String text = ctx.getText(); + Integer instruction = labelVisitor.getInstructionForLabel(text); + if (instruction == null) + { + throw new RuntimeException("reference to unknown label " + text); + } + + int target = instruction // target instruction index + - (pos - 1) // pos is already at the instruction after the switch, so - 1 + - 1; // to go to the instruction prior to target + + LookupSwitch ls = switches.get(pos - 1); + assert ls != null; + + LookupCase scase = ls.getCases().get(ls.getCases().size() - 1); + scase.setOffset(target); + } + + public ScriptDefinition buildScript() + { + setSwitchOperands(); + + ScriptDefinition script = new ScriptDefinition(); + script.setId(id); + script.setIntStackCount(intStackCount); + script.setStringStackCount(stringStackCount); + script.setLocalIntCount(localIntCount); + script.setLocalStringCount(localStringCount); + script.setInstructions(opcodes.stream().mapToInt(Integer::valueOf).toArray()); + script.setIntOperands(iops.stream() + .map(i -> i == null ? 0 : i) + .mapToInt(Integer::valueOf) + .toArray()); + script.setStringOperands(sops.toArray(new String[0])); + script.setSwitches(buildSwitches()); + return script; + } + + private void setSwitchOperands() + { + int count = 0; + for (int i = 0; i < opcodes.size(); ++i) + { + if (opcodes.get(i) != Opcodes.SWITCH) + { + continue; + } + + iops.set(i, count++); + } + } + + private Map[] buildSwitches() + { + int count = (int) switches.stream().filter(Objects::nonNull).count(); + + if (count == 0) + { + return null; + } + + int index = 0; + @SuppressWarnings("unchecked") Map[] maps = new Map[count]; + for (LookupSwitch lswitch : switches) + { + if (lswitch == null) + { + continue; + } + + Map map = maps[index++] = new HashMap<>(); + + for (LookupCase scase : lswitch.getCases()) + { + map.put(scase.getValue(), scase.getOffset()); + } + } + return maps; + } +} diff --git a/src/main/java/net/runelite/cache/script/assembler/rs2asmBaseListener.java b/src/main/java/net/runelite/cache/script/assembler/rs2asmBaseListener.java new file mode 100644 index 0000000..b793e66 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/assembler/rs2asmBaseListener.java @@ -0,0 +1,554 @@ +// Generated from net\runelite\cache\script\assembler\rs2asm.g4 by ANTLR 4.6 +package net.runelite.cache.script.assembler; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.TerminalNode; + +/** + * This class provides an empty implementation of {@link rs2asmListener}, + * which can be extended to create a listener which only needs to handle a subset + * of the available methods. + */ +public class rs2asmBaseListener implements rs2asmListener +{ + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterProg(rs2asmParser.ProgContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitProg(rs2asmParser.ProgContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterHeader(rs2asmParser.HeaderContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitHeader(rs2asmParser.HeaderContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterId(rs2asmParser.IdContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitId(rs2asmParser.IdContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterInt_stack_count(rs2asmParser.Int_stack_countContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitInt_stack_count(rs2asmParser.Int_stack_countContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterString_stack_count(rs2asmParser.String_stack_countContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitString_stack_count(rs2asmParser.String_stack_countContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterInt_var_count(rs2asmParser.Int_var_countContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitInt_var_count(rs2asmParser.Int_var_countContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterString_var_count(rs2asmParser.String_var_countContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitString_var_count(rs2asmParser.String_var_countContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterId_value(rs2asmParser.Id_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitId_value(rs2asmParser.Id_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterInt_stack_value(rs2asmParser.Int_stack_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitInt_stack_value(rs2asmParser.Int_stack_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterString_stack_value(rs2asmParser.String_stack_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitString_stack_value(rs2asmParser.String_stack_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterInt_var_value(rs2asmParser.Int_var_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitInt_var_value(rs2asmParser.Int_var_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterString_var_value(rs2asmParser.String_var_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitString_var_value(rs2asmParser.String_var_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterLine(rs2asmParser.LineContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitLine(rs2asmParser.LineContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterInstruction(rs2asmParser.InstructionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitInstruction(rs2asmParser.InstructionContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterLabel(rs2asmParser.LabelContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitLabel(rs2asmParser.LabelContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterInstruction_name(rs2asmParser.Instruction_nameContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitInstruction_name(rs2asmParser.Instruction_nameContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterName_string(rs2asmParser.Name_stringContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitName_string(rs2asmParser.Name_stringContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterName_opcode(rs2asmParser.Name_opcodeContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitName_opcode(rs2asmParser.Name_opcodeContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterInstruction_operand(rs2asmParser.Instruction_operandContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitInstruction_operand(rs2asmParser.Instruction_operandContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterOperand_int(rs2asmParser.Operand_intContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitOperand_int(rs2asmParser.Operand_intContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterOperand_qstring(rs2asmParser.Operand_qstringContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitOperand_qstring(rs2asmParser.Operand_qstringContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterOperand_label(rs2asmParser.Operand_labelContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitOperand_label(rs2asmParser.Operand_labelContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterSwitch_lookup(rs2asmParser.Switch_lookupContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitSwitch_lookup(rs2asmParser.Switch_lookupContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterSwitch_key(rs2asmParser.Switch_keyContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitSwitch_key(rs2asmParser.Switch_keyContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterSwitch_value(rs2asmParser.Switch_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitSwitch_value(rs2asmParser.Switch_valueContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void visitTerminal(TerminalNode node) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void visitErrorNode(ErrorNode node) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void enterEveryRule(ParserRuleContext ctx) + { + } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override + public void exitEveryRule(ParserRuleContext ctx) + { + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/script/assembler/rs2asmLexer.java b/src/main/java/net/runelite/cache/script/assembler/rs2asmLexer.java new file mode 100644 index 0000000..1505539 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/assembler/rs2asmLexer.java @@ -0,0 +1,171 @@ +// Generated from net\runelite\cache\script\assembler\rs2asm.g4 by ANTLR 4.6 +package net.runelite.cache.script.assembler; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.RuntimeMetaData; +import org.antlr.v4.runtime.Vocabulary; +import org.antlr.v4.runtime.VocabularyImpl; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNDeserializer; +import org.antlr.v4.runtime.atn.LexerATNSimulator; +import org.antlr.v4.runtime.atn.PredictionContextCache; +import org.antlr.v4.runtime.dfa.DFA; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class rs2asmLexer extends Lexer +{ + public static final int + T__0 = 1, T__1 = 2, T__2 = 3, T__3 = 4, T__4 = 5, T__5 = 6, NEWLINE = 7, INT = 8, QSTRING = 9, + IDENTIFIER = 10, COMMENT = 11, WS = 12; + public static final String[] ruleNames = { + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "NEWLINE", "INT", "QSTRING", + "IDENTIFIER", "COMMENT", "WS" + }; + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2\16\u0099\b\1\4\2" + + "\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4" + + "\13\t\13\4\f\t\f\4\r\t\r\3\2\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3" + + "\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\4" + + "\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3" + + "\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6" + + "\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3" + + "\b\6\bn\n\b\r\b\16\bo\3\t\5\ts\n\t\3\t\6\tv\n\t\r\t\16\tw\3\n\3\n\3\n" + + "\3\n\7\n~\n\n\f\n\16\n\u0081\13\n\3\n\3\n\3\13\6\13\u0086\n\13\r\13\16" + + "\13\u0087\3\f\3\f\7\f\u008c\n\f\f\f\16\f\u008f\13\f\3\f\3\f\3\r\6\r\u0094" + + "\n\r\r\r\16\r\u0095\3\r\3\r\2\2\16\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n" + + "\23\13\25\f\27\r\31\16\3\2\b\4\2\f\f\17\17\3\2\62;\6\2\f\f\17\17$$^^\4" + + "\2$$^^\6\2\62;C\\aac|\4\2\13\13\"\"\u00a0\2\3\3\2\2\2\2\5\3\2\2\2\2\7" + + "\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2" + + "\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\3\33\3\2\2\2\5" + + " \3\2\2\2\7\62\3\2\2\2\tG\3\2\2\2\13W\3\2\2\2\rj\3\2\2\2\17m\3\2\2\2\21" + + "r\3\2\2\2\23y\3\2\2\2\25\u0085\3\2\2\2\27\u0089\3\2\2\2\31\u0093\3\2\2" + + "\2\33\34\7\60\2\2\34\35\7k\2\2\35\36\7f\2\2\36\37\7\"\2\2\37\4\3\2\2\2" + + " !\7\60\2\2!\"\7k\2\2\"#\7p\2\2#$\7v\2\2$%\7a\2\2%&\7u\2\2&\'\7v\2\2\'" + + "(\7c\2\2()\7e\2\2)*\7m\2\2*+\7a\2\2+,\7e\2\2,-\7q\2\2-.\7w\2\2./\7p\2" + + "\2/\60\7v\2\2\60\61\7\"\2\2\61\6\3\2\2\2\62\63\7\60\2\2\63\64\7u\2\2\64" + + "\65\7v\2\2\65\66\7t\2\2\66\67\7k\2\2\678\7p\2\289\7i\2\29:\7a\2\2:;\7" + + "u\2\2;<\7v\2\2<=\7c\2\2=>\7e\2\2>?\7m\2\2?@\7a\2\2@A\7e\2\2AB\7q\2\2B" + + "C\7w\2\2CD\7p\2\2DE\7v\2\2EF\7\"\2\2F\b\3\2\2\2GH\7\60\2\2HI\7k\2\2IJ" + + "\7p\2\2JK\7v\2\2KL\7a\2\2LM\7x\2\2MN\7c\2\2NO\7t\2\2OP\7a\2\2PQ\7e\2\2" + + "QR\7q\2\2RS\7w\2\2ST\7p\2\2TU\7v\2\2UV\7\"\2\2V\n\3\2\2\2WX\7\60\2\2X" + + "Y\7u\2\2YZ\7v\2\2Z[\7t\2\2[\\\7k\2\2\\]\7p\2\2]^\7i\2\2^_\7a\2\2_`\7x" + + "\2\2`a\7c\2\2ab\7t\2\2bc\7a\2\2cd\7e\2\2de\7q\2\2ef\7w\2\2fg\7p\2\2gh" + + "\7v\2\2hi\7\"\2\2i\f\3\2\2\2jk\7<\2\2k\16\3\2\2\2ln\t\2\2\2ml\3\2\2\2" + + "no\3\2\2\2om\3\2\2\2op\3\2\2\2p\20\3\2\2\2qs\7/\2\2rq\3\2\2\2rs\3\2\2" + + "\2su\3\2\2\2tv\t\3\2\2ut\3\2\2\2vw\3\2\2\2wu\3\2\2\2wx\3\2\2\2x\22\3\2" + + "\2\2y\177\7$\2\2z~\n\4\2\2{|\7^\2\2|~\t\5\2\2}z\3\2\2\2}{\3\2\2\2~\u0081" + + "\3\2\2\2\177}\3\2\2\2\177\u0080\3\2\2\2\u0080\u0082\3\2\2\2\u0081\177" + + "\3\2\2\2\u0082\u0083\7$\2\2\u0083\24\3\2\2\2\u0084\u0086\t\6\2\2\u0085" + + "\u0084\3\2\2\2\u0086\u0087\3\2\2\2\u0087\u0085\3\2\2\2\u0087\u0088\3\2" + + "\2\2\u0088\26\3\2\2\2\u0089\u008d\7=\2\2\u008a\u008c\n\2\2\2\u008b\u008a" + + "\3\2\2\2\u008c\u008f\3\2\2\2\u008d\u008b\3\2\2\2\u008d\u008e\3\2\2\2\u008e" + + "\u0090\3\2\2\2\u008f\u008d\3\2\2\2\u0090\u0091\b\f\2\2\u0091\30\3\2\2" + + "\2\u0092\u0094\t\7\2\2\u0093\u0092\3\2\2\2\u0094\u0095\3\2\2\2\u0095\u0093" + + "\3\2\2\2\u0095\u0096\3\2\2\2\u0096\u0097\3\2\2\2\u0097\u0098\b\r\2\2\u0098" + + "\32\3\2\2\2\13\2orw}\177\u0087\u008d\u0095\3\2\3\2"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + private static final String[] _LITERAL_NAMES = { + null, "'.id '", "'.int_stack_count '", "'.string_stack_count '", "'.int_var_count '", + "'.string_var_count '", "':'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, "NEWLINE", "INT", "QSTRING", + "IDENTIFIER", "COMMENT", "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + static + { + RuntimeMetaData.checkVersion("4.6", RuntimeMetaData.VERSION); + } + + static + { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) + { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) + { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) + { + tokenNames[i] = ""; + } + } + } + + static + { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) + { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } + + public rs2asmLexer(CharStream input) + { + super(input); + _interp = new LexerATNSimulator(this, _ATN, _decisionToDFA, _sharedContextCache); + } + + @Override + public String[] getRuleNames() + { + return ruleNames; + } + + @Override + + public Vocabulary getVocabulary() + { + return VOCABULARY; + } + + @Override + public String getSerializedATN() + { + return _serializedATN; + } + + @Override + public String getGrammarFileName() + { + return "rs2asm.g4"; + } + + @Override + public ATN getATN() + { + return _ATN; + } + + @Override + public String[] getModeNames() + { + return modeNames; + } + + @Override + @Deprecated + public String[] getTokenNames() + { + return tokenNames; + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/script/assembler/rs2asmListener.java b/src/main/java/net/runelite/cache/script/assembler/rs2asmListener.java new file mode 100644 index 0000000..d4d8e39 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/assembler/rs2asmListener.java @@ -0,0 +1,361 @@ +// Generated from net\runelite\cache\script\assembler\rs2asm.g4 by ANTLR 4.6 +package net.runelite.cache.script.assembler; + +import org.antlr.v4.runtime.tree.ParseTreeListener; + +/** + * This interface defines a complete listener for a parse tree produced by + * {@link rs2asmParser}. + */ +public interface rs2asmListener extends ParseTreeListener +{ + /** + * Enter a parse tree produced by {@link rs2asmParser#prog}. + * + * @param ctx the parse tree + */ + void enterProg(rs2asmParser.ProgContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#prog}. + * + * @param ctx the parse tree + */ + void exitProg(rs2asmParser.ProgContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#header}. + * + * @param ctx the parse tree + */ + void enterHeader(rs2asmParser.HeaderContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#header}. + * + * @param ctx the parse tree + */ + void exitHeader(rs2asmParser.HeaderContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#id}. + * + * @param ctx the parse tree + */ + void enterId(rs2asmParser.IdContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#id}. + * + * @param ctx the parse tree + */ + void exitId(rs2asmParser.IdContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#int_stack_count}. + * + * @param ctx the parse tree + */ + void enterInt_stack_count(rs2asmParser.Int_stack_countContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#int_stack_count}. + * + * @param ctx the parse tree + */ + void exitInt_stack_count(rs2asmParser.Int_stack_countContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#string_stack_count}. + * + * @param ctx the parse tree + */ + void enterString_stack_count(rs2asmParser.String_stack_countContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#string_stack_count}. + * + * @param ctx the parse tree + */ + void exitString_stack_count(rs2asmParser.String_stack_countContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#int_var_count}. + * + * @param ctx the parse tree + */ + void enterInt_var_count(rs2asmParser.Int_var_countContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#int_var_count}. + * + * @param ctx the parse tree + */ + void exitInt_var_count(rs2asmParser.Int_var_countContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#string_var_count}. + * + * @param ctx the parse tree + */ + void enterString_var_count(rs2asmParser.String_var_countContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#string_var_count}. + * + * @param ctx the parse tree + */ + void exitString_var_count(rs2asmParser.String_var_countContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#id_value}. + * + * @param ctx the parse tree + */ + void enterId_value(rs2asmParser.Id_valueContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#id_value}. + * + * @param ctx the parse tree + */ + void exitId_value(rs2asmParser.Id_valueContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#int_stack_value}. + * + * @param ctx the parse tree + */ + void enterInt_stack_value(rs2asmParser.Int_stack_valueContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#int_stack_value}. + * + * @param ctx the parse tree + */ + void exitInt_stack_value(rs2asmParser.Int_stack_valueContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#string_stack_value}. + * + * @param ctx the parse tree + */ + void enterString_stack_value(rs2asmParser.String_stack_valueContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#string_stack_value}. + * + * @param ctx the parse tree + */ + void exitString_stack_value(rs2asmParser.String_stack_valueContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#int_var_value}. + * + * @param ctx the parse tree + */ + void enterInt_var_value(rs2asmParser.Int_var_valueContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#int_var_value}. + * + * @param ctx the parse tree + */ + void exitInt_var_value(rs2asmParser.Int_var_valueContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#string_var_value}. + * + * @param ctx the parse tree + */ + void enterString_var_value(rs2asmParser.String_var_valueContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#string_var_value}. + * + * @param ctx the parse tree + */ + void exitString_var_value(rs2asmParser.String_var_valueContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#line}. + * + * @param ctx the parse tree + */ + void enterLine(rs2asmParser.LineContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#line}. + * + * @param ctx the parse tree + */ + void exitLine(rs2asmParser.LineContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#instruction}. + * + * @param ctx the parse tree + */ + void enterInstruction(rs2asmParser.InstructionContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#instruction}. + * + * @param ctx the parse tree + */ + void exitInstruction(rs2asmParser.InstructionContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#label}. + * + * @param ctx the parse tree + */ + void enterLabel(rs2asmParser.LabelContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#label}. + * + * @param ctx the parse tree + */ + void exitLabel(rs2asmParser.LabelContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#instruction_name}. + * + * @param ctx the parse tree + */ + void enterInstruction_name(rs2asmParser.Instruction_nameContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#instruction_name}. + * + * @param ctx the parse tree + */ + void exitInstruction_name(rs2asmParser.Instruction_nameContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#name_string}. + * + * @param ctx the parse tree + */ + void enterName_string(rs2asmParser.Name_stringContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#name_string}. + * + * @param ctx the parse tree + */ + void exitName_string(rs2asmParser.Name_stringContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#name_opcode}. + * + * @param ctx the parse tree + */ + void enterName_opcode(rs2asmParser.Name_opcodeContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#name_opcode}. + * + * @param ctx the parse tree + */ + void exitName_opcode(rs2asmParser.Name_opcodeContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#instruction_operand}. + * + * @param ctx the parse tree + */ + void enterInstruction_operand(rs2asmParser.Instruction_operandContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#instruction_operand}. + * + * @param ctx the parse tree + */ + void exitInstruction_operand(rs2asmParser.Instruction_operandContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#operand_int}. + * + * @param ctx the parse tree + */ + void enterOperand_int(rs2asmParser.Operand_intContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#operand_int}. + * + * @param ctx the parse tree + */ + void exitOperand_int(rs2asmParser.Operand_intContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#operand_qstring}. + * + * @param ctx the parse tree + */ + void enterOperand_qstring(rs2asmParser.Operand_qstringContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#operand_qstring}. + * + * @param ctx the parse tree + */ + void exitOperand_qstring(rs2asmParser.Operand_qstringContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#operand_label}. + * + * @param ctx the parse tree + */ + void enterOperand_label(rs2asmParser.Operand_labelContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#operand_label}. + * + * @param ctx the parse tree + */ + void exitOperand_label(rs2asmParser.Operand_labelContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#switch_lookup}. + * + * @param ctx the parse tree + */ + void enterSwitch_lookup(rs2asmParser.Switch_lookupContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#switch_lookup}. + * + * @param ctx the parse tree + */ + void exitSwitch_lookup(rs2asmParser.Switch_lookupContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#switch_key}. + * + * @param ctx the parse tree + */ + void enterSwitch_key(rs2asmParser.Switch_keyContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#switch_key}. + * + * @param ctx the parse tree + */ + void exitSwitch_key(rs2asmParser.Switch_keyContext ctx); + + /** + * Enter a parse tree produced by {@link rs2asmParser#switch_value}. + * + * @param ctx the parse tree + */ + void enterSwitch_value(rs2asmParser.Switch_valueContext ctx); + + /** + * Exit a parse tree produced by {@link rs2asmParser#switch_value}. + * + * @param ctx the parse tree + */ + void exitSwitch_value(rs2asmParser.Switch_valueContext ctx); +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/script/assembler/rs2asmParser.java b/src/main/java/net/runelite/cache/script/assembler/rs2asmParser.java new file mode 100644 index 0000000..2905806 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/assembler/rs2asmParser.java @@ -0,0 +1,2000 @@ +// Generated from net\runelite\cache\script\assembler\rs2asm.g4 by ANTLR 4.6 +package net.runelite.cache.script.assembler; + +import java.util.List; +import org.antlr.v4.runtime.NoViableAltException; +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.RuntimeMetaData; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.Vocabulary; +import org.antlr.v4.runtime.VocabularyImpl; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNDeserializer; +import org.antlr.v4.runtime.atn.ParserATNSimulator; +import org.antlr.v4.runtime.atn.PredictionContextCache; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.tree.ParseTreeListener; +import org.antlr.v4.runtime.tree.TerminalNode; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class rs2asmParser extends Parser +{ + public static final int + T__0 = 1, T__1 = 2, T__2 = 3, T__3 = 4, T__4 = 5, T__5 = 6, NEWLINE = 7, INT = 8, QSTRING = 9, + IDENTIFIER = 10, COMMENT = 11, WS = 12; + public static final int + RULE_prog = 0, RULE_header = 1, RULE_id = 2, RULE_int_stack_count = 3, + RULE_string_stack_count = 4, RULE_int_var_count = 5, RULE_string_var_count = 6, + RULE_id_value = 7, RULE_int_stack_value = 8, RULE_string_stack_value = 9, + RULE_int_var_value = 10, RULE_string_var_value = 11, RULE_line = 12, RULE_instruction = 13, + RULE_label = 14, RULE_instruction_name = 15, RULE_name_string = 16, RULE_name_opcode = 17, + RULE_instruction_operand = 18, RULE_operand_int = 19, RULE_operand_qstring = 20, + RULE_operand_label = 21, RULE_switch_lookup = 22, RULE_switch_key = 23, + RULE_switch_value = 24; + public static final String[] ruleNames = { + "prog", "header", "id", "int_stack_count", "string_stack_count", "int_var_count", + "string_var_count", "id_value", "int_stack_value", "string_stack_value", + "int_var_value", "string_var_value", "line", "instruction", "label", "instruction_name", + "name_string", "name_opcode", "instruction_operand", "operand_int", "operand_qstring", + "operand_label", "switch_lookup", "switch_key", "switch_value" + }; + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + public static final String _serializedATN = + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\16\u0097\4\2\t\2" + + "\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13" + + "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22" + + "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31" + + "\4\32\t\32\3\2\7\2\66\n\2\f\2\16\29\13\2\3\2\3\2\6\2=\n\2\r\2\16\2>\7" + + "\2A\n\2\f\2\16\2D\13\2\3\2\3\2\6\2H\n\2\r\2\16\2I\6\2L\n\2\r\2\16\2M\3" + + "\3\3\3\3\3\3\3\3\3\5\3U\n\3\3\4\3\4\3\4\3\5\3\5\3\5\3\6\3\6\3\6\3\7\3" + + "\7\3\7\3\b\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\16\3\16" + + "\3\16\5\16s\n\16\3\17\3\17\3\17\3\20\3\20\3\20\3\21\3\21\5\21}\n\21\3" + + "\22\3\22\3\23\3\23\3\24\3\24\3\24\3\24\5\24\u0087\n\24\3\25\3\25\3\26" + + "\3\26\3\27\3\27\3\30\3\30\3\30\3\30\3\31\3\31\3\32\3\32\3\32\2\2\33\2" + + "\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\2\2\u008c\2\67\3" + + "\2\2\2\4T\3\2\2\2\6V\3\2\2\2\bY\3\2\2\2\n\\\3\2\2\2\f_\3\2\2\2\16b\3\2" + + "\2\2\20e\3\2\2\2\22g\3\2\2\2\24i\3\2\2\2\26k\3\2\2\2\30m\3\2\2\2\32r\3" + + "\2\2\2\34t\3\2\2\2\36w\3\2\2\2 |\3\2\2\2\"~\3\2\2\2$\u0080\3\2\2\2&\u0086" + + "\3\2\2\2(\u0088\3\2\2\2*\u008a\3\2\2\2,\u008c\3\2\2\2.\u008e\3\2\2\2\60" + + "\u0092\3\2\2\2\62\u0094\3\2\2\2\64\66\7\t\2\2\65\64\3\2\2\2\669\3\2\2" + + "\2\67\65\3\2\2\2\678\3\2\2\28B\3\2\2\29\67\3\2\2\2:<\5\4\3\2;=\7\t\2\2" + + "<;\3\2\2\2=>\3\2\2\2><\3\2\2\2>?\3\2\2\2?A\3\2\2\2@:\3\2\2\2AD\3\2\2\2" + + "B@\3\2\2\2BC\3\2\2\2CK\3\2\2\2DB\3\2\2\2EG\5\32\16\2FH\7\t\2\2GF\3\2\2" + + "\2HI\3\2\2\2IG\3\2\2\2IJ\3\2\2\2JL\3\2\2\2KE\3\2\2\2LM\3\2\2\2MK\3\2\2" + + "\2MN\3\2\2\2N\3\3\2\2\2OU\5\6\4\2PU\5\b\5\2QU\5\n\6\2RU\5\f\7\2SU\5\16" + + "\b\2TO\3\2\2\2TP\3\2\2\2TQ\3\2\2\2TR\3\2\2\2TS\3\2\2\2U\5\3\2\2\2VW\7" + + "\3\2\2WX\5\20\t\2X\7\3\2\2\2YZ\7\4\2\2Z[\5\22\n\2[\t\3\2\2\2\\]\7\5\2" + + "\2]^\5\24\13\2^\13\3\2\2\2_`\7\6\2\2`a\5\26\f\2a\r\3\2\2\2bc\7\7\2\2c" + + "d\5\30\r\2d\17\3\2\2\2ef\7\n\2\2f\21\3\2\2\2gh\7\n\2\2h\23\3\2\2\2ij\7" + + "\n\2\2j\25\3\2\2\2kl\7\n\2\2l\27\3\2\2\2mn\7\n\2\2n\31\3\2\2\2os\5\34" + + "\17\2ps\5\36\20\2qs\5.\30\2ro\3\2\2\2rp\3\2\2\2rq\3\2\2\2s\33\3\2\2\2" + + "tu\5 \21\2uv\5&\24\2v\35\3\2\2\2wx\7\f\2\2xy\7\b\2\2y\37\3\2\2\2z}\5\"" + + "\22\2{}\5$\23\2|z\3\2\2\2|{\3\2\2\2}!\3\2\2\2~\177\7\f\2\2\177#\3\2\2" + + "\2\u0080\u0081\7\n\2\2\u0081%\3\2\2\2\u0082\u0087\5(\25\2\u0083\u0087" + + "\5*\26\2\u0084\u0087\5,\27\2\u0085\u0087\3\2\2\2\u0086\u0082\3\2\2\2\u0086" + + "\u0083\3\2\2\2\u0086\u0084\3\2\2\2\u0086\u0085\3\2\2\2\u0087\'\3\2\2\2" + + "\u0088\u0089\7\n\2\2\u0089)\3\2\2\2\u008a\u008b\7\13\2\2\u008b+\3\2\2" + + "\2\u008c\u008d\7\f\2\2\u008d-\3\2\2\2\u008e\u008f\5\60\31\2\u008f\u0090" + + "\7\b\2\2\u0090\u0091\5\62\32\2\u0091/\3\2\2\2\u0092\u0093\7\n\2\2\u0093" + + "\61\3\2\2\2\u0094\u0095\7\f\2\2\u0095\63\3\2\2\2\13\67>BIMTr|\u0086"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + private static final String[] _LITERAL_NAMES = { + null, "'.id '", "'.int_stack_count '", "'.string_stack_count '", "'.int_var_count '", + "'.string_var_count '", "':'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, "NEWLINE", "INT", "QSTRING", + "IDENTIFIER", "COMMENT", "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + static + { + RuntimeMetaData.checkVersion("4.6", RuntimeMetaData.VERSION); + } + + static + { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) + { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) + { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) + { + tokenNames[i] = ""; + } + } + } + + static + { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) + { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } + + public rs2asmParser(TokenStream input) + { + super(input); + _interp = new ParserATNSimulator(this, _ATN, _decisionToDFA, _sharedContextCache); + } + + @Override + @Deprecated + public String[] getTokenNames() + { + return tokenNames; + } + + @Override + public String[] getRuleNames() + { + return ruleNames; + } + + @Override + + public Vocabulary getVocabulary() + { + return VOCABULARY; + } + + @Override + public String getSerializedATN() + { + return _serializedATN; + } + + @Override + public String getGrammarFileName() + { + return "rs2asm.g4"; + } + + @Override + public ATN getATN() + { + return _ATN; + } + + public final ProgContext prog() throws RecognitionException + { + ProgContext _localctx = new ProgContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_prog); + int _la; + try + { + enterOuterAlt(_localctx, 1); + { + setState(53); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la == NEWLINE) + { + { + { + setState(50); + match(NEWLINE); + } + } + setState(55); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(64); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__1) | (1L << T__2) | (1L << T__3) | (1L << T__4))) != 0)) + { + { + { + setState(56); + header(); + setState(58); + _errHandler.sync(this); + _la = _input.LA(1); + do + { + { + { + setState(57); + match(NEWLINE); + } + } + setState(60); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == NEWLINE); + } + } + setState(66); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(73); + _errHandler.sync(this); + _la = _input.LA(1); + do + { + { + { + setState(67); + line(); + setState(69); + _errHandler.sync(this); + _la = _input.LA(1); + do + { + { + { + setState(68); + match(NEWLINE); + } + } + setState(71); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == NEWLINE); + } + } + setState(75); + _errHandler.sync(this); + _la = _input.LA(1); + } while (_la == INT || _la == IDENTIFIER); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final HeaderContext header() throws RecognitionException + { + HeaderContext _localctx = new HeaderContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_header); + try + { + setState(82); + _errHandler.sync(this); + switch (_input.LA(1)) + { + case T__0: + enterOuterAlt(_localctx, 1); + { + setState(77); + id(); + } + break; + case T__1: + enterOuterAlt(_localctx, 2); + { + setState(78); + int_stack_count(); + } + break; + case T__2: + enterOuterAlt(_localctx, 3); + { + setState(79); + string_stack_count(); + } + break; + case T__3: + enterOuterAlt(_localctx, 4); + { + setState(80); + int_var_count(); + } + break; + case T__4: + enterOuterAlt(_localctx, 5); + { + setState(81); + string_var_count(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final IdContext id() throws RecognitionException + { + IdContext _localctx = new IdContext(_ctx, getState()); + enterRule(_localctx, 4, RULE_id); + try + { + enterOuterAlt(_localctx, 1); + { + setState(84); + match(T__0); + setState(85); + id_value(); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Int_stack_countContext int_stack_count() throws RecognitionException + { + Int_stack_countContext _localctx = new Int_stack_countContext(_ctx, getState()); + enterRule(_localctx, 6, RULE_int_stack_count); + try + { + enterOuterAlt(_localctx, 1); + { + setState(87); + match(T__1); + setState(88); + int_stack_value(); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final String_stack_countContext string_stack_count() throws RecognitionException + { + String_stack_countContext _localctx = new String_stack_countContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_string_stack_count); + try + { + enterOuterAlt(_localctx, 1); + { + setState(90); + match(T__2); + setState(91); + string_stack_value(); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Int_var_countContext int_var_count() throws RecognitionException + { + Int_var_countContext _localctx = new Int_var_countContext(_ctx, getState()); + enterRule(_localctx, 10, RULE_int_var_count); + try + { + enterOuterAlt(_localctx, 1); + { + setState(93); + match(T__3); + setState(94); + int_var_value(); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final String_var_countContext string_var_count() throws RecognitionException + { + String_var_countContext _localctx = new String_var_countContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_string_var_count); + try + { + enterOuterAlt(_localctx, 1); + { + setState(96); + match(T__4); + setState(97); + string_var_value(); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Id_valueContext id_value() throws RecognitionException + { + Id_valueContext _localctx = new Id_valueContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_id_value); + try + { + enterOuterAlt(_localctx, 1); + { + setState(99); + match(INT); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Int_stack_valueContext int_stack_value() throws RecognitionException + { + Int_stack_valueContext _localctx = new Int_stack_valueContext(_ctx, getState()); + enterRule(_localctx, 16, RULE_int_stack_value); + try + { + enterOuterAlt(_localctx, 1); + { + setState(101); + match(INT); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final String_stack_valueContext string_stack_value() throws RecognitionException + { + String_stack_valueContext _localctx = new String_stack_valueContext(_ctx, getState()); + enterRule(_localctx, 18, RULE_string_stack_value); + try + { + enterOuterAlt(_localctx, 1); + { + setState(103); + match(INT); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Int_var_valueContext int_var_value() throws RecognitionException + { + Int_var_valueContext _localctx = new Int_var_valueContext(_ctx, getState()); + enterRule(_localctx, 20, RULE_int_var_value); + try + { + enterOuterAlt(_localctx, 1); + { + setState(105); + match(INT); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final String_var_valueContext string_var_value() throws RecognitionException + { + String_var_valueContext _localctx = new String_var_valueContext(_ctx, getState()); + enterRule(_localctx, 22, RULE_string_var_value); + try + { + enterOuterAlt(_localctx, 1); + { + setState(107); + match(INT); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final LineContext line() throws RecognitionException + { + LineContext _localctx = new LineContext(_ctx, getState()); + enterRule(_localctx, 24, RULE_line); + try + { + setState(112); + _errHandler.sync(this); + switch (getInterpreter().adaptivePredict(_input, 6, _ctx)) + { + case 1: + enterOuterAlt(_localctx, 1); + { + setState(109); + instruction(); + } + break; + case 2: + enterOuterAlt(_localctx, 2); + { + setState(110); + label(); + } + break; + case 3: + enterOuterAlt(_localctx, 3); + { + setState(111); + switch_lookup(); + } + break; + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final InstructionContext instruction() throws RecognitionException + { + InstructionContext _localctx = new InstructionContext(_ctx, getState()); + enterRule(_localctx, 26, RULE_instruction); + try + { + enterOuterAlt(_localctx, 1); + { + setState(114); + instruction_name(); + setState(115); + instruction_operand(); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final LabelContext label() throws RecognitionException + { + LabelContext _localctx = new LabelContext(_ctx, getState()); + enterRule(_localctx, 28, RULE_label); + try + { + enterOuterAlt(_localctx, 1); + { + setState(117); + match(IDENTIFIER); + setState(118); + match(T__5); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Instruction_nameContext instruction_name() throws RecognitionException + { + Instruction_nameContext _localctx = new Instruction_nameContext(_ctx, getState()); + enterRule(_localctx, 30, RULE_instruction_name); + try + { + setState(122); + _errHandler.sync(this); + switch (_input.LA(1)) + { + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(120); + name_string(); + } + break; + case INT: + enterOuterAlt(_localctx, 2); + { + setState(121); + name_opcode(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Name_stringContext name_string() throws RecognitionException + { + Name_stringContext _localctx = new Name_stringContext(_ctx, getState()); + enterRule(_localctx, 32, RULE_name_string); + try + { + enterOuterAlt(_localctx, 1); + { + setState(124); + match(IDENTIFIER); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Name_opcodeContext name_opcode() throws RecognitionException + { + Name_opcodeContext _localctx = new Name_opcodeContext(_ctx, getState()); + enterRule(_localctx, 34, RULE_name_opcode); + try + { + enterOuterAlt(_localctx, 1); + { + setState(126); + match(INT); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Instruction_operandContext instruction_operand() throws RecognitionException + { + Instruction_operandContext _localctx = new Instruction_operandContext(_ctx, getState()); + enterRule(_localctx, 36, RULE_instruction_operand); + try + { + setState(132); + _errHandler.sync(this); + switch (_input.LA(1)) + { + case INT: + enterOuterAlt(_localctx, 1); + { + setState(128); + operand_int(); + } + break; + case QSTRING: + enterOuterAlt(_localctx, 2); + { + setState(129); + operand_qstring(); + } + break; + case IDENTIFIER: + enterOuterAlt(_localctx, 3); + { + setState(130); + operand_label(); + } + break; + case NEWLINE: + enterOuterAlt(_localctx, 4); + { + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Operand_intContext operand_int() throws RecognitionException + { + Operand_intContext _localctx = new Operand_intContext(_ctx, getState()); + enterRule(_localctx, 38, RULE_operand_int); + try + { + enterOuterAlt(_localctx, 1); + { + setState(134); + match(INT); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Operand_qstringContext operand_qstring() throws RecognitionException + { + Operand_qstringContext _localctx = new Operand_qstringContext(_ctx, getState()); + enterRule(_localctx, 40, RULE_operand_qstring); + try + { + enterOuterAlt(_localctx, 1); + { + setState(136); + match(QSTRING); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Operand_labelContext operand_label() throws RecognitionException + { + Operand_labelContext _localctx = new Operand_labelContext(_ctx, getState()); + enterRule(_localctx, 42, RULE_operand_label); + try + { + enterOuterAlt(_localctx, 1); + { + setState(138); + match(IDENTIFIER); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Switch_lookupContext switch_lookup() throws RecognitionException + { + Switch_lookupContext _localctx = new Switch_lookupContext(_ctx, getState()); + enterRule(_localctx, 44, RULE_switch_lookup); + try + { + enterOuterAlt(_localctx, 1); + { + setState(140); + switch_key(); + setState(141); + match(T__5); + setState(142); + switch_value(); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Switch_keyContext switch_key() throws RecognitionException + { + Switch_keyContext _localctx = new Switch_keyContext(_ctx, getState()); + enterRule(_localctx, 46, RULE_switch_key); + try + { + enterOuterAlt(_localctx, 1); + { + setState(144); + match(INT); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public final Switch_valueContext switch_value() throws RecognitionException + { + Switch_valueContext _localctx = new Switch_valueContext(_ctx, getState()); + enterRule(_localctx, 48, RULE_switch_value); + try + { + enterOuterAlt(_localctx, 1); + { + setState(146); + match(IDENTIFIER); + } + } + catch (RecognitionException re) + { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally + { + exitRule(); + } + return _localctx; + } + + public static class ProgContext extends ParserRuleContext + { + public ProgContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public List NEWLINE() + { + return getTokens(rs2asmParser.NEWLINE); + } + + public TerminalNode NEWLINE(int i) + { + return getToken(rs2asmParser.NEWLINE, i); + } + + public List header() + { + return getRuleContexts(HeaderContext.class); + } + + public HeaderContext header(int i) + { + return getRuleContext(HeaderContext.class, i); + } + + public List line() + { + return getRuleContexts(LineContext.class); + } + + public LineContext line(int i) + { + return getRuleContext(LineContext.class, i); + } + + @Override + public int getRuleIndex() + { + return RULE_prog; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterProg(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitProg(this); + } + } + } + + public static class HeaderContext extends ParserRuleContext + { + public HeaderContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public IdContext id() + { + return getRuleContext(IdContext.class, 0); + } + + public Int_stack_countContext int_stack_count() + { + return getRuleContext(Int_stack_countContext.class, 0); + } + + public String_stack_countContext string_stack_count() + { + return getRuleContext(String_stack_countContext.class, 0); + } + + public Int_var_countContext int_var_count() + { + return getRuleContext(Int_var_countContext.class, 0); + } + + public String_var_countContext string_var_count() + { + return getRuleContext(String_var_countContext.class, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_header; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterHeader(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitHeader(this); + } + } + } + + public static class IdContext extends ParserRuleContext + { + public IdContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public Id_valueContext id_value() + { + return getRuleContext(Id_valueContext.class, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_id; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterId(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitId(this); + } + } + } + + public static class Int_stack_countContext extends ParserRuleContext + { + public Int_stack_countContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public Int_stack_valueContext int_stack_value() + { + return getRuleContext(Int_stack_valueContext.class, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_int_stack_count; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterInt_stack_count(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitInt_stack_count(this); + } + } + } + + public static class String_stack_countContext extends ParserRuleContext + { + public String_stack_countContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public String_stack_valueContext string_stack_value() + { + return getRuleContext(String_stack_valueContext.class, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_string_stack_count; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterString_stack_count(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitString_stack_count(this); + } + } + } + + public static class Int_var_countContext extends ParserRuleContext + { + public Int_var_countContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public Int_var_valueContext int_var_value() + { + return getRuleContext(Int_var_valueContext.class, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_int_var_count; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterInt_var_count(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitInt_var_count(this); + } + } + } + + public static class String_var_countContext extends ParserRuleContext + { + public String_var_countContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public String_var_valueContext string_var_value() + { + return getRuleContext(String_var_valueContext.class, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_string_var_count; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterString_var_count(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitString_var_count(this); + } + } + } + + public static class Id_valueContext extends ParserRuleContext + { + public Id_valueContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode INT() + { + return getToken(rs2asmParser.INT, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_id_value; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterId_value(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitId_value(this); + } + } + } + + public static class Int_stack_valueContext extends ParserRuleContext + { + public Int_stack_valueContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode INT() + { + return getToken(rs2asmParser.INT, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_int_stack_value; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterInt_stack_value(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitInt_stack_value(this); + } + } + } + + public static class String_stack_valueContext extends ParserRuleContext + { + public String_stack_valueContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode INT() + { + return getToken(rs2asmParser.INT, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_string_stack_value; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterString_stack_value(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitString_stack_value(this); + } + } + } + + public static class Int_var_valueContext extends ParserRuleContext + { + public Int_var_valueContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode INT() + { + return getToken(rs2asmParser.INT, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_int_var_value; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterInt_var_value(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitInt_var_value(this); + } + } + } + + public static class String_var_valueContext extends ParserRuleContext + { + public String_var_valueContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode INT() + { + return getToken(rs2asmParser.INT, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_string_var_value; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterString_var_value(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitString_var_value(this); + } + } + } + + public static class LineContext extends ParserRuleContext + { + public LineContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public InstructionContext instruction() + { + return getRuleContext(InstructionContext.class, 0); + } + + public LabelContext label() + { + return getRuleContext(LabelContext.class, 0); + } + + public Switch_lookupContext switch_lookup() + { + return getRuleContext(Switch_lookupContext.class, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_line; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterLine(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitLine(this); + } + } + } + + public static class InstructionContext extends ParserRuleContext + { + public InstructionContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public Instruction_nameContext instruction_name() + { + return getRuleContext(Instruction_nameContext.class, 0); + } + + public Instruction_operandContext instruction_operand() + { + return getRuleContext(Instruction_operandContext.class, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_instruction; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterInstruction(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitInstruction(this); + } + } + } + + public static class LabelContext extends ParserRuleContext + { + public LabelContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode IDENTIFIER() + { + return getToken(rs2asmParser.IDENTIFIER, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_label; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterLabel(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitLabel(this); + } + } + } + + public static class Instruction_nameContext extends ParserRuleContext + { + public Instruction_nameContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public Name_stringContext name_string() + { + return getRuleContext(Name_stringContext.class, 0); + } + + public Name_opcodeContext name_opcode() + { + return getRuleContext(Name_opcodeContext.class, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_instruction_name; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterInstruction_name(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitInstruction_name(this); + } + } + } + + public static class Name_stringContext extends ParserRuleContext + { + public Name_stringContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode IDENTIFIER() + { + return getToken(rs2asmParser.IDENTIFIER, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_name_string; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterName_string(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitName_string(this); + } + } + } + + public static class Name_opcodeContext extends ParserRuleContext + { + public Name_opcodeContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode INT() + { + return getToken(rs2asmParser.INT, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_name_opcode; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterName_opcode(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitName_opcode(this); + } + } + } + + public static class Instruction_operandContext extends ParserRuleContext + { + public Instruction_operandContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public Operand_intContext operand_int() + { + return getRuleContext(Operand_intContext.class, 0); + } + + public Operand_qstringContext operand_qstring() + { + return getRuleContext(Operand_qstringContext.class, 0); + } + + public Operand_labelContext operand_label() + { + return getRuleContext(Operand_labelContext.class, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_instruction_operand; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterInstruction_operand(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitInstruction_operand(this); + } + } + } + + public static class Operand_intContext extends ParserRuleContext + { + public Operand_intContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode INT() + { + return getToken(rs2asmParser.INT, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_operand_int; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterOperand_int(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitOperand_int(this); + } + } + } + + public static class Operand_qstringContext extends ParserRuleContext + { + public Operand_qstringContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode QSTRING() + { + return getToken(rs2asmParser.QSTRING, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_operand_qstring; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterOperand_qstring(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitOperand_qstring(this); + } + } + } + + public static class Operand_labelContext extends ParserRuleContext + { + public Operand_labelContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode IDENTIFIER() + { + return getToken(rs2asmParser.IDENTIFIER, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_operand_label; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterOperand_label(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitOperand_label(this); + } + } + } + + public static class Switch_lookupContext extends ParserRuleContext + { + public Switch_lookupContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public Switch_keyContext switch_key() + { + return getRuleContext(Switch_keyContext.class, 0); + } + + public Switch_valueContext switch_value() + { + return getRuleContext(Switch_valueContext.class, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_switch_lookup; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterSwitch_lookup(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitSwitch_lookup(this); + } + } + } + + public static class Switch_keyContext extends ParserRuleContext + { + public Switch_keyContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode INT() + { + return getToken(rs2asmParser.INT, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_switch_key; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterSwitch_key(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitSwitch_key(this); + } + } + } + + public static class Switch_valueContext extends ParserRuleContext + { + public Switch_valueContext(ParserRuleContext parent, int invokingState) + { + super(parent, invokingState); + } + + public TerminalNode IDENTIFIER() + { + return getToken(rs2asmParser.IDENTIFIER, 0); + } + + @Override + public int getRuleIndex() + { + return RULE_switch_value; + } + + @Override + public void enterRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).enterSwitch_value(this); + } + } + + @Override + public void exitRule(ParseTreeListener listener) + { + if (listener instanceof rs2asmListener) + { + ((rs2asmListener) listener).exitSwitch_value(this); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/net/runelite/cache/script/disassembler/Disassembler.java b/src/main/java/net/runelite/cache/script/disassembler/Disassembler.java new file mode 100644 index 0000000..0a6382f --- /dev/null +++ b/src/main/java/net/runelite/cache/script/disassembler/Disassembler.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.script.disassembler; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; +import net.runelite.cache.definitions.ScriptDefinition; +import net.runelite.cache.script.Instruction; +import net.runelite.cache.script.Instructions; +import net.runelite.cache.script.Opcodes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Disassembler +{ + private static final Logger logger = LoggerFactory.getLogger(Disassembler.class); + + private final Instructions instructions = new Instructions(); + + public Disassembler() + { + instructions.init(); + } + + private boolean isJump(int opcode) + { + switch (opcode) + { + case Opcodes.JUMP: + case Opcodes.IF_ICMPEQ: + case Opcodes.IF_ICMPGE: + case Opcodes.IF_ICMPGT: + case Opcodes.IF_ICMPLE: + case Opcodes.IF_ICMPLT: + case Opcodes.IF_ICMPNE: + return true; + default: + return false; + } + } + + private boolean[] needLabel(ScriptDefinition script) + { + int[] instructions = script.getInstructions(); + int[] iops = script.getIntOperands(); + Map[] switches = script.getSwitches(); + + boolean[] jumped = new boolean[instructions.length]; + + for (int i = 0; i < instructions.length; ++i) + { + int opcode = instructions[i]; + int iop = iops[i]; + + if (opcode == Opcodes.SWITCH) + { + Map switchMap = switches[iop]; + + for (Entry entry : switchMap.entrySet()) + { + int offset = entry.getValue(); + + int to = i + offset + 1; + assert to >= 0 && to < instructions.length; + jumped[to] = true; + } + } + + if (!isJump(opcode)) + { + continue; + } + + // + 1 because the jumps go to the instructions prior to the + // one you really want, because the pc is incremented on the + // next loop + int to = i + iop + 1; + assert to >= 0 && to < instructions.length; + + jumped[to] = true; + } + + return jumped; + } + + public String disassemble(ScriptDefinition script) throws IOException + { + int[] instructions = script.getInstructions(); + int[] iops = script.getIntOperands(); + String[] sops = script.getStringOperands(); + Map[] switches = script.getSwitches(); + + assert iops.length == instructions.length; + assert sops.length == instructions.length; + + boolean[] jumps = needLabel(script); + + StringBuilder writer = new StringBuilder(); + writerHeader(writer, script); + + for (int i = 0; i < instructions.length; ++i) + { + int opcode = instructions[i]; + int iop = iops[i]; + String sop = sops[i]; + + Instruction ins = this.instructions.find(opcode); + if (ins == null) + { + logger.warn("Unknown instruction {} in script {}", opcode, script.getId()); + } + + if (jumps[i]) + { + // something jumps here + writer.append("LABEL").append(i).append(":\n"); + } + + String name; + if (ins != null && ins.getName() != null) + { + name = ins.getName(); + } + else + { + name = String.format("%03d", opcode); + } + + writer.append(String.format(" %-22s", name)); + + if (shouldWriteIntOperand(opcode, iop)) + { + if (isJump(opcode)) + { + writer.append(" LABEL").append(i + iop + 1); + } + else + { + writer.append(" ").append(iop); + } + } + + if (sop != null) + { + writer.append(" \"").append(sop).append("\""); + } + + if (opcode == Opcodes.SWITCH) + { + Map switchMap = switches[iop]; + + for (Entry entry : switchMap.entrySet()) + { + int value = entry.getKey(); + int jump = entry.getValue(); + + writer.append("\n"); + writer.append(" ").append(value).append(": LABEL").append(i + jump + 1); + } + } + + writer.append("\n"); + } + + return writer.toString(); + } + + private boolean shouldWriteIntOperand(int opcode, int operand) + { + if (opcode == Opcodes.SWITCH) + { + // table follows instruction + return false; + } + + if (operand != 0) + { + // always write non-zero operand + return true; + } + + switch (opcode) + { + case Opcodes.ICONST: + case Opcodes.ILOAD: + case Opcodes.SLOAD: + case Opcodes.ISTORE: + case Opcodes.SSTORE: + return true; + } + + // int operand is not used, don't write it + return false; + } + + private void writerHeader(StringBuilder writer, ScriptDefinition script) + { + int id = script.getId(); + int intStackCount = script.getIntStackCount(); + int stringStackCount = script.getStringStackCount(); + int localIntCount = script.getLocalIntCount(); + int localStringCount = script.getLocalStringCount(); + + writer.append(".id ").append(id).append('\n'); + writer.append(".int_stack_count ").append(intStackCount).append('\n'); + writer.append(".string_stack_count ").append(stringStackCount).append('\n'); + writer.append(".int_var_count ").append(localIntCount).append('\n'); + writer.append(".string_var_count ").append(localStringCount).append('\n'); + } +} diff --git a/src/main/java/net/runelite/cache/script/rs2asm.tokens b/src/main/java/net/runelite/cache/script/rs2asm.tokens new file mode 100644 index 0000000..de505a0 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/rs2asm.tokens @@ -0,0 +1,18 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +NEWLINE=7 +INT=8 +QSTRING=9 +IDENTIFIER=10 +COMMENT=11 +WS=12 +'.id '=1 +'.int_stack_count '=2 +'.string_stack_count '=3 +'.int_var_count '=4 +'.string_var_count '=5 +':'=6 diff --git a/src/main/java/net/runelite/cache/script/rs2asmLexer.tokens b/src/main/java/net/runelite/cache/script/rs2asmLexer.tokens new file mode 100644 index 0000000..de505a0 --- /dev/null +++ b/src/main/java/net/runelite/cache/script/rs2asmLexer.tokens @@ -0,0 +1,18 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +NEWLINE=7 +INT=8 +QSTRING=9 +IDENTIFIER=10 +COMMENT=11 +WS=12 +'.id '=1 +'.int_stack_count '=2 +'.string_stack_count '=3 +'.int_var_count '=4 +'.string_var_count '=5 +':'=6 diff --git a/src/main/java/net/runelite/cache/util/BZip2.java b/src/main/java/net/runelite/cache/util/BZip2.java new file mode 100644 index 0000000..cde6fc5 --- /dev/null +++ b/src/main/java/net/runelite/cache/util/BZip2.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; +import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; +import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream; +import org.apache.commons.compress.utils.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BZip2 +{ + private static final Logger logger = LoggerFactory.getLogger(BZip2.class); + + private static final byte[] BZIP_HEADER = new byte[] + { + 'B', 'Z', // magic + 'h', // 'h' for Bzip2 ('H'uffman coding) + '1' // block size + }; + + public static byte[] compress(byte[] bytes) throws IOException + { + InputStream is = new ByteArrayInputStream(bytes); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + try (OutputStream os = new BZip2CompressorOutputStream(bout, 1)) + { + IOUtils.copy(is, os); + } + + byte[] out = bout.toByteArray(); + + assert BZIP_HEADER[0] == out[0]; + assert BZIP_HEADER[1] == out[1]; + assert BZIP_HEADER[2] == out[2]; + assert BZIP_HEADER[3] == out[3]; + + return Arrays.copyOfRange(out, BZIP_HEADER.length, out.length); // remove header.. + } + + public static byte[] decompress(byte[] bytes, int len) throws IOException + { + byte[] data = new byte[len + BZIP_HEADER.length]; + + // add header + System.arraycopy(BZIP_HEADER, 0, data, 0, BZIP_HEADER.length); + System.arraycopy(bytes, 0, data, BZIP_HEADER.length, len); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + try (InputStream is = new BZip2CompressorInputStream(new ByteArrayInputStream(data))) + { + IOUtils.copy(is, os); + } + + return os.toByteArray(); + } +} diff --git a/src/main/java/net/runelite/cache/util/Crc32.java b/src/main/java/net/runelite/cache/util/Crc32.java new file mode 100644 index 0000000..929ddd4 --- /dev/null +++ b/src/main/java/net/runelite/cache/util/Crc32.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.util; + +import java.util.zip.CRC32; + +public class Crc32 +{ + private final CRC32 crc32 = new CRC32(); + + public void update(byte[] data, int offset, int length) + { + crc32.update(data, offset, length); + } + + public int getHash() + { + return (int) crc32.getValue(); + } +} diff --git a/src/main/java/net/runelite/cache/util/Djb2.java b/src/main/java/net/runelite/cache/util/Djb2.java new file mode 100644 index 0000000..e6ccc13 --- /dev/null +++ b/src/main/java/net/runelite/cache/util/Djb2.java @@ -0,0 +1,28 @@ +package net.runelite.cache.util; + +/** + * An implementation of the {@code djb2} hash function. + * + * @author Graham + * @author `Discardedx2 + */ +public final class Djb2 +{ + /** + * An implementation of Dan Bernstein's {@code djb2} hash function which + * is slightly modified. Instead of the initial hash being 5381, it is + * zero. + * + * @param str The string to hash. + * @return The hash code. + */ + public static int hash(String str) + { + int hash = 0; + for (int i = 0; i < str.length(); i++) + { + hash = str.charAt(i) + ((hash << 5) - hash); + } + return hash; + } +} diff --git a/src/main/java/net/runelite/cache/util/Djb2Manager.java b/src/main/java/net/runelite/cache/util/Djb2Manager.java new file mode 100644 index 0000000..5db676f --- /dev/null +++ b/src/main/java/net/runelite/cache/util/Djb2Manager.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.util; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Djb2Manager +{ + private static final Logger logger = LoggerFactory.getLogger(Djb2Manager.class); + + private final Map hashes = new HashMap<>(); + + public void load() throws IOException + { + Properties properties = new Properties(); + properties.load(Djb2Manager.class.getResourceAsStream("/djb2.properties")); + + for (Object key : properties.keySet()) + { + int hash = Integer.parseInt((String) key); + String value = properties.getProperty((String) key); + + hashes.put(hash, value); + } + + logger.info("Loaded {} djb2 hashes", hashes.size()); + } + + public String getName(int hash) + { + return hashes.get(hash); + } +} diff --git a/src/main/java/net/runelite/cache/util/GZip.java b/src/main/java/net/runelite/cache/util/GZip.java new file mode 100644 index 0000000..faae86e --- /dev/null +++ b/src/main/java/net/runelite/cache/util/GZip.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package net.runelite.cache.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; +import org.apache.commons.compress.utils.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GZip +{ + private static final Logger logger = LoggerFactory.getLogger(GZip.class); + + public static byte[] compress(byte[] bytes) throws IOException + { + InputStream is = new ByteArrayInputStream(bytes); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + + try (OutputStream os = new GZIPOutputStream(bout)) + { + IOUtils.copy(is, os); + } + + return bout.toByteArray(); + } + + public static byte[] decompress(byte[] bytes, int len) throws IOException + { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + try (InputStream is = new GZIPInputStream(new ByteArrayInputStream(bytes, 0, len))) + { + IOUtils.copy(is, os); + } + + return os.toByteArray(); + } +} diff --git a/src/main/java/net/runelite/cache/util/IDClass.java b/src/main/java/net/runelite/cache/util/IDClass.java new file mode 100644 index 0000000..e647fb2 --- /dev/null +++ b/src/main/java/net/runelite/cache/util/IDClass.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.util; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; + +public class IDClass extends PrintWriter +{ + private final Namer namer = new Namer(); + + private IDClass(File file) throws FileNotFoundException + { + super(file); + } + + public static IDClass create(File directory, String name) throws IOException + { + IDClass c = new IDClass(new File(directory, name + ".java")); + c.println("/* This file is automatically generated. Do not edit. */"); + c.println("package net.runelite.api;"); + c.println(); + c.print("public final class "); + c.println(name); + c.println("{"); + return c; + } + + public void add(String name, int id) + { + String javaName = namer.name(name, id); + if (javaName == null) + { + return; + } + + println(" public static final int " + javaName + " = " + id + ";"); + } + + @Override + public void println() + { + // Java 9+ only reads line.separator on startup, so we have to override it here + write('\n'); + } + + @Override + public void close() + { + println("\t/* This file is automatically generated. Do not edit. */"); + println("}"); + super.close(); + } +} diff --git a/src/main/java/net/runelite/cache/util/Namer.java b/src/main/java/net/runelite/cache/util/Namer.java new file mode 100644 index 0000000..834da31 --- /dev/null +++ b/src/main/java/net/runelite/cache/util/Namer.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017, Adam + * Copyright (c) 2018, Joshua Filby + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.util; + +import java.util.HashSet; +import java.util.Set; + +public class Namer +{ + private final Set used = new HashSet<>(); + + public String name(String name, int id) + { + name = sanitize(name); + + if (name == null) + { + return null; + } + + if (used.contains(name)) + { + name = name + "_" + id; + assert !used.contains(name); + } + + used.add(name); + + return name; + } + + private static String sanitize(String in) + { + String s = removeTags(in) + .toUpperCase() + .replace(' ', '_') + .replaceAll("[^a-zA-Z0-9_]", ""); + if (s.isEmpty()) + { + return null; + } + if (Character.isDigit(s.charAt(0))) + { + return "_" + s; + } + else + { + return s; + } + } + + public static String removeTags(String str) + { + StringBuilder builder = new StringBuilder(str.length()); + boolean inTag = false; + + for (int i = 0; i < str.length(); i++) + { + char currentChar = str.charAt(i); + + if (currentChar == '<') + { + inTag = true; + } + else if (currentChar == '>') + { + inTag = false; + } + else if (!inTag) + { + builder.append(currentChar); + } + } + + return builder.toString(); + } +} diff --git a/src/main/java/net/runelite/cache/util/ScriptVarType.java b/src/main/java/net/runelite/cache/util/ScriptVarType.java new file mode 100644 index 0000000..bda13d8 --- /dev/null +++ b/src/main/java/net/runelite/cache/util/ScriptVarType.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018, Joshua Filby + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.util; + +import java.util.HashMap; +import java.util.Map; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public enum ScriptVarType +{ + INTEGER('i', "integer"), + BOOLEAN('1', "boolean"), + SEQ('A', "seq"), + COLOUR('C', "colour"), + /** + * Also known as {@code Widget}. + */ + COMPONENT('I', "component"), + IDKIT('K', "idkit"), + MIDI('M', "midi"), + SYNTH('P', "synth"), + STAT('S', "stat"), + COORDGRID('c', "coordgrid"), + GRAPHIC('d', "graphic"), + FONTMETRICS('f', "fontmetrics"), + ENUM('g', "enum"), + JINGLE('j', "jingle"), + /** + * Also known as {@code Object}. + */ + LOC('l', "loc"), + MODEL('m', "model"), + NPC('n', "npc"), + /** + * Also known as {@code Item}. + */ + OBJ('o', "obj"), + /** + * Another version of {@code OBJ}, but means that on Jagex's side they used the internal name for an item. + */ + NAMEDOBJ('O', "namedobj"), + STRING('s', "string"), + SPOTANIM('t', "spotanim"), + INV('v', "inv"), + TEXTURE('x', "texture"), + CHAR('z', "char"), + MAPSCENEICON('£', "mapsceneicon"), + MAPELEMENT('µ', "mapelement"), + HITMARK('×', "hitmark"), + STRUCT('J', "struct"); + + private static final Map keyToTypeMap = new HashMap<>(); + + static + { + for (ScriptVarType type : values()) + { + keyToTypeMap.put(type.keyChar, type); + } + } + + /** + * The character used when encoding or decoding types. + */ + private final char keyChar; + /** + * The full name of the var type. + */ + private final String fullName; + + public static ScriptVarType forCharKey(char key) + { + return keyToTypeMap.get(key); + } + +} diff --git a/src/main/java/net/runelite/cache/util/Xtea.java b/src/main/java/net/runelite/cache/util/Xtea.java new file mode 100644 index 0000000..c79dc5a --- /dev/null +++ b/src/main/java/net/runelite/cache/util/Xtea.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.util; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +public class Xtea +{ + private static final int GOLDEN_RATIO = 0x9E3779B9; + + private static final int ROUNDS = 32; + + private final int[] key; + + public Xtea(int[] key) + { + this.key = key; + } + + public byte[] encrypt(byte[] data, int len) + { + ByteBuf buf = Unpooled.wrappedBuffer(data, 0, len); + ByteBuf out = Unpooled.buffer(len); + int numBlocks = len / 8; + for (int block = 0; block < numBlocks; ++block) + { + int v0 = buf.readInt(); + int v1 = buf.readInt(); + int sum = 0; + for (int i = 0; i < ROUNDS; ++i) + { + v0 += (((v1 << 4) ^ (v1 >>> 5)) + v1) ^ (sum + key[sum & 3]); + sum += GOLDEN_RATIO; + v1 += (((v0 << 4) ^ (v0 >>> 5)) + v0) ^ (sum + key[(sum >>> 11) & 3]); + } + out.writeInt(v0); + out.writeInt(v1); + } + out.writeBytes(buf); + return out.array(); + } + + public byte[] decrypt(byte[] data, int len) + { + ByteBuf buf = Unpooled.wrappedBuffer(data, 0, len); + ByteBuf out = Unpooled.buffer(len); + int numBlocks = len / 8; + for (int block = 0; block < numBlocks; ++block) + { + int v0 = buf.readInt(); + int v1 = buf.readInt(); + int sum = GOLDEN_RATIO * ROUNDS; + for (int i = 0; i < ROUNDS; ++i) + { + v1 -= (((v0 << 4) ^ (v0 >>> 5)) + v0) ^ (sum + key[(sum >>> 11) & 3]); + sum -= GOLDEN_RATIO; + v0 -= (((v1 << 4) ^ (v1 >>> 5)) + v1) ^ (sum + key[sum & 3]); + } + out.writeInt(v0); + out.writeInt(v1); + } + out.writeBytes(buf); + return out.array(); + } +} diff --git a/src/main/java/net/runelite/cache/util/XteaKeyManager.java b/src/main/java/net/runelite/cache/util/XteaKeyManager.java new file mode 100644 index 0000000..468ab48 --- /dev/null +++ b/src/main/java/net/runelite/cache/util/XteaKeyManager.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.util; + +import java.util.HashMap; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class XteaKeyManager +{ + private static final Logger logger = LoggerFactory.getLogger(XteaKeyManager.class); + + private final Map keys = new HashMap<>(); + + public void loadKeys() + { + + } + + public int[] getKeys(int region) + { + return keys.get(region); + } +} diff --git a/src/main/resources/djb2.properties b/src/main/resources/djb2.properties new file mode 100644 index 0000000..87c3bb8 --- /dev/null +++ b/src/main/resources/djb2.properties @@ -0,0 +1,1403 @@ +#Wed Nov 29 15:08:06 PST 2017 +-1863637185=miscgraphics,4 +-1863637184=miscgraphics,5 +-1863637187=miscgraphics,2 +-1863637186=miscgraphics,3 +-1863637181=miscgraphics,8 +-1863637180=miscgraphics,9 +-440204630=alls fairy in love n war +-1863637183=miscgraphics,6 +-1253085654=scorpia_dances +-1863637182=miscgraphics,7 +1356196826=backvmid3 +-751102526=high seas +1356196825=backvmid2 +-1863637189=miscgraphics,0 +549358875=camelot +-1863637188=miscgraphics,1 +-1619800378=emotes_locked,19 +-1619800379=emotes_locked,18 +792536868=understanding +1356196824=backvmid1 +-1773559904=title_mute +-342013218=p11_full +1523653533=pirates of peril +696768774=harmony +-1701556831=magicoff2,27 +281586976=orb_icon,3 +286265996=ready for battle +-1701556832=magicoff2,26 +281586977=orb_icon,4 +-645977478=scape scared +-1701556833=magicoff2,25 +281586978=orb_icon,5 +-1701556834=magicoff2,24 +-1701556830=magicoff2,28 +-1052794696=dance of death +-1619800383=emotes_locked,14 +-1619800384=emotes_locked,13 +-1619800385=emotes_locked,12 +-1556842207=sl_flags +-1619800386=emotes_locked,11 +1614826739=mapletree +-1619800387=emotes_locked,10 +-1701556835=magicoff2,23 +-1701556836=magicoff2,22 +1363656441=serenade +-1701556837=magicoff2,21 +3089326=door +-1701556838=magicoff2,20 +-1619800380=emotes_locked,17 +-1619800381=emotes_locked,16 +-1619800382=emotes_locked,15 +-1037172987=tomorrow +825974316=melodrama +281586973=orb_icon,0 +281586974=orb_icon,1 +281586975=orb_icon,2 +-1701556864=magicoff2,15 +-1701556865=magicoff2,14 +-1701556866=magicoff2,13 +1509400204=sarcophagus +-1701556867=magicoff2,12 +-1701556860=magicoff2,19 +-1701556861=magicoff2,18 +-1701556862=magicoff2,17 +1868377358=lower_depths +-1701556863=magicoff2,16 +1086036315=reggae2 +-1220755677=hermit +-1544597765=sl_stars +-1619800350=emotes_locked,26 +-1619800351=emotes_locked,25 +-1636062434=tex_brown +-1619800352=emotes_locked,24 +-1619800353=emotes_locked,23 +-2122174648=back to life +-1619800354=emotes_locked,22 +-1701556868=magicoff2,11 +-1619800355=emotes_locked,21 +-1701556869=magicoff2,10 +-1619800356=emotes_locked,20 +1619539773=side_icons,7 +1121239524=scape wild +368271413=diango's little helpers +1619539772=side_icons,6 +1619539775=side_icons,9 +1619539774=side_icons,8 +-1938172321=miscgraphics2,0 +1619539771=side_icons,5 +1619539770=side_icons,4 +-926977577=the enchanter +1202794514=doorways +1343649581=schools out +-1097177625=q8_full +756012174=wornicons,4 +756012173=wornicons,3 +756012176=wornicons,6 +756012175=wornicons,5 +756012170=wornicons,0 +827249681=ogre the top +756012172=wornicons,2 +756012171=wornicons,1 +-1741764817=poles apart +756012178=wornicons,8 +-1938172320=miscgraphics2,1 +756012177=wornicons,7 +-43136286=the last shanty +756012179=wornicons,9 +837131331=mapback +-1938172313=miscgraphics2,8 +907740319=the depths +-1938172312=miscgraphics2,9 +-2099722614=cave of beasts +-1938172317=miscgraphics2,4 +-1938172316=miscgraphics2,5 +-1938172315=miscgraphics2,6 +-1938172314=miscgraphics2,7 +1619539769=side_icons,3 +-1367483767=cavern +-1938172319=miscgraphics2,2 +50474489=treestump +-1938172318=miscgraphics2,3 +1619539766=side_icons,0 +1619539768=side_icons,2 +1619539767=side_icons,1 +-607416954=prayeron,11 +1837251043=melzars maze +-607416953=prayeron,12 +1318893900=have an ice day +-607416952=prayeron,13 +-1701556800=magicoff2,37 +-607416951=prayeron,14 +-1701556801=magicoff2,36 +-56804840=woodland +-607416950=prayeron,15 +1120636327=scape cave +358884868=button_red +-1701556806=magicoff2,31 +-1701556807=magicoff2,30 +-1701556802=magicoff2,35 +-1701556803=magicoff2,34 +-1701556804=magicoff2,33 +-1858265682=monster melee +-1701556805=magicoff2,32 +-649484675=land of the dwarves +-1789903512=golden touch +1328851780=close_buttons,6 +1080306793=shayzien_march +-1339126929=damage +4820960=monkey sadness +-1951786153=bone dance +1328851781=close_buttons,7 +939546513=forlorn_homestead +-1019905269=shadowland +-607416955=prayeron,10 +-2048535896=pheasant peasant +-1025233830=monkey madness +1121125956=scape soft +-1562452687=etcetera +1969878996=emotes,47 +1969878994=emotes,45 +-1228279872=ge_icons,3 +1969878995=emotes,46 +-1228279871=ge_icons,4 +1969878992=emotes,43 +-1228279870=ge_icons,5 +1969878993=emotes,44 +1959803992=invback +399048409=mage arena +1969878990=emotes,41 +-47057524=lasting +1969878991=emotes,42 +-1228279875=ge_icons,0 +-1228279874=ge_icons,1 +-1228279873=ge_icons,2 +-1860080918=inspiration +1997757502=redstone2 +1997757503=redstone3 +-1060046352=tribal2 +1997757501=redstone1 +-1701556829=magicoff2,29 +1890607210=magicon2,37 +1890607211=magicon2,38 +1890607212=magicon2,39 +-1408684838=ascent +-848436598=fishing +-119984250=combaticons2,17 +-119984251=combaticons2,16 +1769177816=jungle island +-119984252=combaticons2,15 +-119984253=combaticons2,14 +-119984254=combaticons2,13 +-119984255=combaticons2,12 +-119984256=combaticons2,11 +-119984257=combaticons2,10 +1890607205=magicon2,32 +1890607206=magicon2,33 +1890607207=magicon2,34 +1890607208=magicon2,35 +135141185=zeah_combat +1890607209=magicon2,36 +-180851958=norse code +112903447=water +922007495=talking forest +-672706748=miracle dance +-1110089645=lament +-1237461365=grotto +1890607203=magicon2,30 +1890607204=magicon2,31 +-1073910849=mirror +-988841056=still night +-1857025509=sunburn +-468596910=easter jig +796868952=major miner +-1066798491=trawler +1640556978=wonderous +-1624274920=emperor +740093634=find my way +1890607238=magicon2,44 +1890607239=magicon2,45 +3559837=tick +-1839713245=sideicons +1029455878=hells bells +1890607234=magicon2,40 +1890607235=magicon2,41 +1890607236=magicon2,42 +1890607237=magicon2,43 +1503566841=forbidden +-895763669=spooky +-276138668=ham attack +500433071=combaticons,5 +-1021014225=catch me if you can +500433070=combaticons,4 +500433073=combaticons,7 +500433072=combaticons,6 +500433075=combaticons,9 +1533565119=mind over matter +500433074=combaticons,8 +2025958358=emotes_locked,4 +500433066=combaticons,0 +2025958357=emotes_locked,3 +862821975=far away +-1228392498=artistry +2025958356=emotes_locked,2 +500433068=combaticons,2 +2025958355=emotes_locked,1 +500433067=combaticons,1 +1085444827=refresh +500433069=combaticons,3 +2025958359=emotes_locked,5 +1427043851=on the up +2025958354=emotes_locked,0 +1316697938=whistle +347955347=venture +1959211608=mapfunction,77 +1959211609=mapfunction,78 +881850881=the chosen +1959211601=mapfunction,70 +1959211602=mapfunction,71 +584643951=lost soul +582140282=rising damp +1959211603=mapfunction,72 +1740872686=soulfall +1959211604=mapfunction,73 +1959211605=mapfunction,74 +-119984248=combaticons2,19 +1959211606=mapfunction,75 +-119984249=combaticons2,18 +1609255038=slither and thither +82917947=sarim's vermin +1959211607=mapfunction,76 +1728911401=natural +-1189743137=duel arena +108698078=roof2 +214634021=head to head +2025958361=emotes_locked,7 +-448773288=isle of everywhere +2025958360=emotes_locked,6 +-1869996941=titlebox +-338347745=showdown +-2075972251=long ago +2025958363=emotes_locked,9 +2025958362=emotes_locked,8 +-1487589606=7th realm +-1253087691=garden +-2133902017=zeah_farming +-492926285=impetuous +3314014=lair +907815588=the desert +-1960860275=barbarianism +1890607241=magicon2,47 +1890607242=magicon2,48 +1890607243=magicon2,49 +-919642451=jungle bells +795515487=underground +561438836=fountain +-1418827919=illusive +-634763748=fruits de mer +1890607240=magicon2,46 +1694458038=large_button +1393517697=bandit camp +1959211632=mapfunction,80 +1884773718=magicoff2,2 +1884773719=magicoff2,3 +1884773716=magicoff2,0 +2121900771=backtop1 +1884773717=magicoff2,1 +-103077377=gnomeball +-1947119982=blistering barnacles +828650857=autumn voyage +92909147=alone +1691516951=undead dungeon +122265833=expecting +-1320617626=dunjun +1959211633=mapfunction,81 +1959211634=mapfunction,82 +1959211635=mapfunction,83 +1959211636=mapfunction,84 +1959211637=mapfunction,85 +777534707=army of darkness +1959211638=mapfunction,86 +1959211639=mapfunction,87 +1884773721=magicoff2,5 +1884773722=magicoff2,6 +1884773720=magicoff2,4 +1959211640=mapfunction,88 +1959211641=mapfunction,89 +-327707013=anywhere +1884773725=magicoff2,9 +1884773723=magicoff2,7 +1884773724=magicoff2,8 +1116844876=incantation +-728886272=temple of light +685934899=in the clink +-1237289460=grumpy +1945133711=inferno +466902883=strange place +-418223472=phasmatys +817472004=zombiism +106578554=zeah_book,0 +106578555=zeah_book,1 +1509070203=eagle peak +-485932799=expedition +1171923143=emotes,8 +-675357975=attack1 +1171923144=emotes,9 +1959211610=mapfunction,79 +-675357974=attack2 +-675357973=attack3 +-675357972=attack4 +-675357971=attack5 +40246002=masquerade +-675357970=attack6 +-734206983=arrival +-1980407601=sea shanty xmas +284435223=pharoah's tomb +-148552909=down below +1171923141=emotes,6 +1171923142=emotes,7 +1171923140=emotes,5 +-1077789440=mellow +-710537653=kingdom +1171923138=emotes,3 +1171923139=emotes,4 +1171923136=emotes,1 +-2098286081=venture2 +1171923137=emotes,2 +1171923135=emotes,0 +-1094248165=sigmunds showdown +-271106892=rat a tat tat +3288564=keys +-143163121=ham fisted +-900633031=medieval +944208821=life's a beach\! +-1228279453=riverside +-1666444059=combaticons,10 +825919125=options_icons,24 +825919126=options_icons,25 +1179379180=the trade parade +-1666444057=combaticons,12 +825919123=options_icons,22 +-1666444058=combaticons,11 +825919124=options_icons,23 +825919121=options_icons,20 +1884768169=magicoff,32 +825919122=options_icons,21 +1884768167=magicoff,30 +1884768168=magicoff,31 +1318818808=chainmail +582031337=intrepid +783525419=beetle juice +432605856=untouchable +-969918857=neverland +79789174=narnode's theme +-705938181=zealot +117588=web +-1666444051=combaticons,18 +-1666444052=combaticons,17 +1687654733=troubled +-1666444050=combaticons,19 +-1666444055=combaticons,14 +825919129=options_icons,28 +-1666444056=combaticons,13 +-1666444053=combaticons,16 +825919127=options_icons,26 +-1666444054=combaticons,15 +825919128=options_icons,27 +1320694328=magical journey +364185053=roll the bones +-1254483584=jungly1 +981183822=right on track +-1254483583=jungly2 +-1254483582=jungly3 +3075958=dark +-2038936746=deep down +1512143976=everlasting fire +-1392319985=beyond +46273615=tale of keldagrim +-651951461=goblin game +3522941=save +104084791=mossy +1250935993=the monsters below +794539501=garden of summer +1814277765=elven mist +2110556093=the golem +-1475251658=where eagles lair +1884768143=magicoff,27 +1884768144=magicoff,28 +1884768141=magicoff,25 +1529837717=bubble and squeak +1884768142=magicoff,26 +-1679325940=technology +1884768145=magicoff,29 +-826562194=troubled_waters +1884768140=magicoff,24 +-1359348243=painting1 +1267356434=the power of tears +-1359348242=painting2 +-860755690=jungle hunt +1884768138=magicoff,22 +-1197347961=magic magic magic +1884768139=magicoff,23 +1134405764=hypnotized +1959211539=mapfunction,50 +1381363755=my arms journey +-1644401602=complication +1959211540=mapfunction,51 +1959211541=mapfunction,52 +1884768136=magicoff,20 +1959211542=mapfunction,53 +2111304827=warning_icons,0 +1884768137=magicoff,21 +-440187560=zogre dance +1959211543=mapfunction,54 +2111304828=warning_icons,1 +-2002535437=corridors of power +825919130=options_icons,29 +580384095=jungle troubles +1301622585=slice of station +1959211544=mapfunction,55 +2111304829=warning_icons,2 +-1294172031=escape +-1309477156=expanse +-1526067851=alternative root +2124773424=dynasty +1743765602=leftarrow +-1482676188=romancing the crone +-1891851953=island of the trolls +736457293=small_button_pressed +-1106172890=letter +986170990=dreamstate +1959211545=mapfunction,56 +1959211546=mapfunction,57 +1765722413=spirits of elid +1959211547=mapfunction,58 +1959211548=mapfunction,59 +-2075333010=lonesome +3314400=lava +1355033875=worldmap_icon,1 +1814357716=knightmare +1690742645=nox_irae +94935104=cross +-1249495153=frogland +-1642689926=athletes foot +107944162=quest +1355033874=worldmap_icon,0 +-2130741313=joy of the hunt +-28982081=labyrinth +250959119=marooned +-1522984472=altar_ego +1326424637=the lost melody +-1779111734=arabique +-398925062=sea shanty2 +1884768110=magicoff,15 +1884768111=magicoff,16 +1817249074=woe of the wyvern +1884768114=magicoff,19 +1884768112=magicoff,17 +-1624760229=emotion +1884768113=magicoff,18 +-353951458=attention +279431252=garden of autumn +422652266=small_button +1884768107=magicoff,12 +1884768108=magicoff,13 +375695247=the far side +1884768105=magicoff,10 +1884768106=magicoff,11 +-528864109=crystal sword +1884768109=magicoff,14 +1959211570=mapfunction,60 +-158141423=prayeron,7 +-158141424=prayeron,6 +1959211571=mapfunction,61 +-158141421=prayeron,9 +1959211572=mapfunction,62 +-158141422=prayeron,8 +1959211573=mapfunction,63 +1959211574=mapfunction,64 +688840255=piscarilius_sigil +1959211575=mapfunction,65 +1959211576=mapfunction,66 +1170407052=headicons_prayer +1959211577=mapfunction,67 +-324496873=soundscape +-1418445703=tex_red +1961540869=wornicons,10 +-1028580907=that_sullen_hall +397136995=elfpainting +-2092714094=haunted mine +1959211578=mapfunction,68 +1959211579=mapfunction,69 +-158141429=prayeron,1 +-158141427=prayeron,3 +-140492390=bunny_sugar_rush +-158141428=prayeron,2 +-158141425=prayeron,5 +1827366203=righteousness +-649601274=darkness_in_the_depths +-158141426=prayeron,4 +1961540870=wornicons,11 +-158141430=prayeron,0 +910299584=principality +-734028978=arrow,1 +-734028979=arrow,0 +790067275=garden of spring +35762567=workshop +-1095396929=competition +96463963=egypt +-1154441378=jollyr +-1685231711=cave background +-2078908549=time out +-1172405897=wildwood +-170561624=spookyjungle +2110231453=mod_icons +2061491048=shining +-1063411723=tremble +94627585=chest +-520702427=ice melody +1346720899=backleft1 +-607416919=prayeron,25 +-607416918=prayeron,26 +900197712=staticons,6 +-607416917=prayeron,27 +900197713=staticons,7 +-607416916=prayeron,28 +900197710=staticons,4 +-607416915=prayeron,29 +900197711=staticons,5 +957931606=courage +900197714=staticons,8 +900197715=staticons,9 +-720253066=the other side +-1655721374=prayeroff,31 +-607416921=prayeron,23 +-1655721375=prayeroff,30 +-607416920=prayeron,24 +-710515142=the mad mole +-1350228392=stratosphere +-1666438445=combaticons2,3 +-1666438446=combaticons2,2 +-1666438443=combaticons2,5 +-1666438444=combaticons2,4 +-1106570438=legion +-1666438441=combaticons2,7 +-1666438442=combaticons2,6 +1398587265=flute salad +-1666438440=combaticons2,8 +837223705=mapedge +900197709=staticons,3 +-243680393=peng_emotes,7 +900197707=staticons,1 +378300078=everlasting +900197708=staticons,2 +-944748869=witching +-243680396=peng_emotes,4 +-1335336992=logo_deadman_mode +-1368714737=small_button_blue +-795140435=wander +-243680397=peng_emotes,3 +-243680394=peng_emotes,6 +-1666438447=combaticons2,1 +-243680395=peng_emotes,5 +-1666438448=combaticons2,0 +-243680398=peng_emotes,2 +-243680399=peng_emotes,1 +-607416924=prayeron,20 +900197706=staticons,0 +-607416923=prayeron,21 +-607416922=prayeron,22 +3016376=bark +-89244313=romper chomper +346288985=dorgeshun deep +1585002399=magicon,21 +-1725263140=chef surprize +1585002398=magicon,20 +-993528987=making waves +-628963539=ham and seek +-1666438439=combaticons2,9 +-333224315=baroque +-1236252722=prime time +280241284=waking dream +-564582358=distant land +115411843=castlewars +1513246078=al kharid +-1377700863=unknown land +1264132816=miles away +1185785872=barbassault_icons,3 +1185785873=barbassault_icons,4 +-1655721397=prayeroff,29 +-1655721398=prayeroff,28 +1185785874=barbassault_icons,5 +-1655721399=prayeroff,27 +1185785875=barbassault_icons,6 +1711341885=fight or flight +1185785870=barbassault_icons,1 +1185785871=barbassault_icons,2 +3530505=sire +-309570839=pick_and_shovel +647234089=distillery hilarity +-127408236=gnome_village_party +1337378554=backbase2 +109757537=stars +1337378553=backbase1 +109757538=start +819884325=wilderness3 +1328851775=close_buttons,1 +658759958=side_background +1328851774=close_buttons,0 +-782211141=wonder +1328851777=close_buttons,3 +-1995718284=wall_white +819884324=wilderness2 +1328851776=close_buttons,2 +1328851779=close_buttons,5 +-943885542=scape hunter +1328851778=close_buttons,4 +1185785869=barbassault_icons,0 +-607416949=prayeron,16 +-607416948=prayeron,17 +-1779684630=rune essence +-607416947=prayeron,18 +-607416946=prayeron,19 +1119460311=bandos battalion +-967559823=creature cruelty +-1904094243=zeah_fishing +-1913214770=wilderness +460367020=village +825919161=options_icons,39 +1585002375=magicon,18 +94839810=coins +1585002376=magicon,19 +825919160=options_icons,38 +-1282090556=faerie +-521895311=the adventurer +788399136=tree spirits +-1902858744=beneath_the_stronghold +-356730043=pirates of penance +1185785876=barbassault_icons,7 +825919158=options_icons,36 +825919159=options_icons,37 +825919156=options_icons,34 +-1455241861=victory is mine +825919157=options_icons,35 +-1333874720=side_icons,17 +825919154=options_icons,32 +825919155=options_icons,33 +825919152=options_icons,30 +825919153=options_icons,31 +1437805631=chatback +-1623296531=ground scape +685190118=in the brine +1366257555=nightfall +110327241=theme +-1333874725=side_icons,12 +-1333874726=side_icons,11 +-1333874727=side_icons,10 +-1333874721=side_icons,16 +-1333874722=side_icons,15 +-1124681475=darkly_altared +-8976533=throne of the demon +-1333874723=side_icons,14 +-1333874724=side_icons,13 +-1989106719=assault and battery +1958759012=greatness +1057075019=b12_full +1143353537=chain of command +-51091830=desert voyage +-1073927447=mirage +-91048728=number_button +3165239=gaol +-1380919269=breeze +445640248=rugged_terrain +106079=key +-655784411=overlay_multiway +-1025835715=backright2 +-1025835716=backright1 +1120933843=scape main +3225350=iban +-956253112=title fight +-123912401=la mort +1585002367=magicon,10 +-2128736428=startgame +1585002368=magicon,11 +-925031874=royale +1585002369=magicon,12 +1585002370=magicon,13 +1585002373=magicon,16 +1585002374=magicon,17 +-1307116191=superstition +1585002371=magicon,14 +1585002372=magicon,15 +-587569902=path of peril +3392903=null +-1601127242=inadequacy +2136330800=staticons2,0 +2136330801=staticons2,1 +344336468=grip of the talon +2136330804=staticons2,4 +2136330805=staticons2,5 +2136330802=staticons2,2 +2136330803=staticons2,3 +1960215130=barking mad +-43712789=scape original +621171714=cellar song +1585002461=magicon,41 +1585002462=magicon,42 +1585002460=magicon,40 +111485446=upass +2136330808=staticons2,8 +694847251=in the manor +2136330809=staticons2,9 +2136330806=staticons2,6 +2136330807=staticons2,7 +-1385847955=rightarrow +1343200077=the slayer +1585002465=magicon,45 +1585002466=magicon,46 +1585002463=magicon,43 +1585002464=magicon,44 +1585002469=magicon,49 +-95571520=volcanic vikings +1585002467=magicon,47 +1585002468=magicon,48 +-1032629963=shipwrecked +93330745=aztec +-881372797=tabs,1 +1377351472=oriental +121641580=headicons_hint +-881372798=tabs,0 +1585002438=magicon,39 +-1661605940=elfwood +-607416893=prayeron,30 +-822106577=jungle island xmas +-607416892=prayeron,31 +332368736=mad eadgar +1585002432=magicon,33 +-143368781=side_background_right +1585002433=magicon,34 +-1081494434=malady +1585002430=magicon,31 +1585002431=magicon,32 +1585002436=magicon,37 +1585002437=magicon,38 +1585002434=magicon,35 +1585002435=magicon,36 +-1938171360=miscgraphics3,0 +-1059680853=trinity +781557721=dies_irae +-1938171359=miscgraphics3,1 +497375231=stillness +-1938171358=miscgraphics3,2 +-1938171357=miscgraphics3,3 +-960709976=dogs of war +2129339089=magicon,1 +2129339088=magicon,0 +755433248=headicons_pk +108392383=regal +-213632750=waterfall +-1367706280=canvas +73828649=settlement +848123561=into the abyss +478781900=last stand +1339486127=the shadow +-1055503808=roc and roll +837204902=mapdots +950484242=compass +-1082154559=fanfare +747848680=nether_realm +788224888=dead quiet +1532279978=monarch waltz +-149029727=side_background_left1 +812947089=fanfare2 +-149029726=side_background_left2 +1006643748=high spirits +-2136059388=starlight +2122572442=the tower +-1998869913=spooky2 +1411067174=gnome village2 +-2065077267=wild side +812947090=fanfare3 +1585002429=magicon,30 +1294629755=on the wing +2097127567=monkey badness +-2032107216=sojourn +1020264019=pest control +3237038=info +1473393027=fe fi fo fum +-1686202291=upper_depths +3540994=stop +1742080803=darkwood +740392969=little cave of horrors +-158379532=prayerglow +-691855347=in between +-200702983=the noble rodent +1652745754=forgotten +-1895307673=hitmark,3 +-1895307674=hitmark,2 +-1895307675=hitmark,1 +-1895307676=hitmark,0 +-1895307670=hitmark,6 +-1895307671=hitmark,5 +-1895307672=hitmark,4 +1968917071=bone dry +-850506182=trawler minor +197029040=mapscene +-808772318=in the pits +-1165315580=looking back +-1763090403=scape_ape +-1938177931=miscgraphics,11 +-1938177932=miscgraphics,10 +1936130561=thrall_of_the_serpent +1258863383=yesteryear +1994744000=slice of silent movie +-1691854169=dead can dance +1585002407=magicon,29 +1585002405=magicon,27 +1585002406=magicon,28 +271319484=frostbite +-499867199=meridian +1585002400=magicon,22 +-1938177930=miscgraphics,12 +-84626226=mudskipper melody +1585002403=magicon,25 +1585002404=magicon,26 +3641802=wall +1585002401=magicon,23 +1585002402=magicon,24 +-606457701=wolf mountain +1276599785=button_brown +1969878899=emotes,13 +1969878897=emotes,11 +1969878898=emotes,12 +1969878896=emotes,10 +-1938177928=miscgraphics,14 +-907669678=brew hoo hoo +-1938177929=miscgraphics,13 +72999866=subterranea +619237947=the galleon +-1764950404=scape sad +295831445=heart and mind +908430134=dangerous road +738888631=tradebacking +-174800339=verdana_11pt_regular +686705631=lightwalk +-601591436=side_background_bottom +-1479412376=the navigator +-359173459=zamorak zoo +744536246=null and void +-1701556798=magicoff2,39 +-1701556799=magicoff2,38 +-1396384012=bamboo +-200388662=lighthouse +133626717=suspicious +-810515425=voyage +3061973=crag +1802291895=big chords +-1661619479=elfwall +113315621=wood2 +1813041183=steelborder2,0 +429244831=slug a bug ball +1813041184=steelborder2,1 +-1658386264=shining_spirit +738909086=chamber +526264239=verdana_13pt_regular +-877351859=temple +2142215577=the mollusc menace +1124498189=warpath +-2136649922=no way out +-339706871=grimly_fiendish +547534551=wrath and ruin +544229147=lore and order +3327206=load +1610073470=lovakengj_sigil +-419218284=long way home +-662489856=food for thought +1306461568=stagnant +-1662171955=elfdoor +-1043985601=meddling kids +947464074=titlebutton +-1309055712=exposed +-1487348923=ambient jungle +-1829469821=lament of meiyerditch +233203434=leftarrow_small +-1216167350=dangerous +114464611=railings +-1106574323=legend +-1701556767=magicoff2,49 +-999707515=time to mine +-1701556768=magicoff2,48 +2129339097=magicon,9 +2129339096=magicon,8 +1959211510=mapfunction,42 +2129339095=magicon,7 +1959211511=mapfunction,43 +2129339094=magicon,6 +2129339093=magicon,5 +2129339092=magicon,4 +2129339091=magicon,3 +2129339090=magicon,2 +3522472=saga +-1701556769=magicoff2,47 +-544722449=rellekka +1033441676=tribal background +1915718129=the desolate isle +1890607150=magicon2,19 +1787618597=stranded +1717999087=forgettable melody +1959211512=mapfunction,44 +-243680400=peng_emotes,0 +1959211513=mapfunction,45 +1959211514=mapfunction,46 +1959211515=mapfunction,47 +1959211516=mapfunction,48 +1959211517=mapfunction,49 +1705947058=the cellar dwellers +1216634785=landlubber +1884768198=magicoff,40 +-1588113323=the rogues den +1884768199=magicoff,41 +-905842564=serene +-607599698=prayeroff,2 +-607599699=prayeroff,1 +1890607142=magicon2,11 +1389384362=monkey trouble +1890607143=magicon2,12 +1890607144=magicon2,13 +1890607145=magicon2,14 +1890607146=magicon2,15 +1890607147=magicon2,16 +1890607148=magicon2,17 +1966766798=mausoleum +1890607149=magicon2,18 +1808345541=armadyl alliance +290391725=options_slider,7 +1890607141=magicon2,10 +290391722=options_slider,4 +-607599696=prayeroff,4 +290391721=options_slider,3 +-607599697=prayeroff,3 +290391724=options_slider,6 +-607599694=prayeroff,6 +290391723=options_slider,5 +-607599695=prayeroff,5 +-607599692=prayeroff,8 +-607599693=prayeroff,7 +290391720=options_slider,2 +-607599691=prayeroff,9 +1334775925=chat_background +-1779127378=arabian2 +-1779127377=arabian3 +528722471=island life +1890607175=magicon2,23 +1890607176=magicon2,24 +949634504=mouse trap +1890607177=magicon2,25 +1890607178=magicon2,26 +1890607179=magicon2,27 +3327403=logo +290391719=options_slider,1 +1092249049=storm brew +290391718=options_slider,0 +404357804=everywhere +1890607172=magicon2,20 +1890607173=magicon2,21 +951530772=contest +1890607174=magicon2,22 +-1701556776=magicoff2,40 +1884768176=magicoff,39 +-395250469=corporal punishment +1749113330=newbie melody +1884768174=magicoff,37 +1884768175=magicoff,38 +-1701556772=magicoff2,44 +-1701556773=magicoff2,43 +-1701556774=magicoff2,42 +-1701556775=magicoff2,41 +-858121616=tzhaar +1884768172=magicoff,35 +1884768173=magicoff,36 +666772244=combat_shield +1884768170=magicoff,33 +1884768171=magicoff,34 +1959211509=mapfunction,41 +1639695510=mapmarker +-1661748240=friends_icons +-552301350=knightly +-1918044851=mastermindless +-1701556770=magicoff2,46 +-1701556771=magicoff2,45 +201526300=corporealbeast +1959211508=mapfunction,40 +105001967=nomad +-70910145=clickcross,3 +-1737914947=mapfunction,5 +1801745440=staticons2,11 +-70910146=clickcross,2 +-865479038=tribal +-1737914946=mapfunction,6 +1801745441=staticons2,12 +-70910147=clickcross,1 +-1737914945=mapfunction,7 +1801745442=staticons2,13 +-70910148=clickcross,0 +-1737914944=mapfunction,8 +1801745443=staticons2,14 +-1737914943=mapfunction,9 +1801745444=staticons2,15 +1801745445=staticons2,16 +1801745446=staticons2,17 +-1877545169=land down under +93921962=books +-1737914949=mapfunction,3 +-1737914948=mapfunction,4 +-1655721428=prayeroff,19 +-2136884405=title.jpg +-1655721429=prayeroff,18 +1584819628=magicoff,6 +1584819629=magicoff,7 +437480876=voodoo cult +1584819624=magicoff,2 +1584819625=magicoff,3 +1584819626=magicoff,4 +-1737914952=mapfunction,0 +1584819627=magicoff,5 +-1737914951=mapfunction,1 +124995564=harmony2 +1584819622=magicoff,0 +1801745439=staticons2,10 +1584819623=magicoff,1 +346263512=dorgeshun city +-1665011705=down and out +1890607180=magicon2,28 +1890607181=magicon2,29 +1417471781=titlescroll +1959211446=mapfunction,20 +1956141536=options_radio_buttons,0 +736568812=ballad of enchantment +-1737914950=mapfunction,2 +1959211447=mapfunction,21 +1959211448=mapfunction,22 +1959211449=mapfunction,23 +-1890130256=morytania +-70910141=clickcross,7 +-70910142=clickcross,6 +1956141539=options_radio_buttons,3 +-70910143=clickcross,5 +1956141538=options_radio_buttons,2 +284766976=splendour +-70910144=clickcross,4 +1956141537=options_radio_buttons,1 +196677638=the quizmaster +530068296=overture +-1123094568=sl_button +-700552779=hosidius_sigil +-614076819=sad meadow +1956141543=options_radio_buttons,7 +1956141542=options_radio_buttons,6 +1956141541=options_radio_buttons,5 +1956141540=options_radio_buttons,4 +1584819631=magicoff,9 +1846633612=gnome village +-2128560371=sl_back +1969878905=emotes,19 +306819362=crystal castle +1584819630=magicoff,8 +1969878903=emotes,17 +303737220=options_icons,7 +1969878904=emotes,18 +1969878901=emotes,15 +-78220817=devils_may_care +1969878902=emotes,16 +-40521666=dimension x +1969878900=emotes,14 +673424924=the lunar isle +789609582=brimstail's scales +303737222=options_icons,9 +303737221=options_icons,8 +1959211415=mapfunction,10 +3059343=coil +1959211416=mapfunction,11 +1959211417=mapfunction,12 +-1256560486=last_man_standing +1959211418=mapfunction,13 +336238005=rightarrow_small +1959211419=mapfunction,14 +-677662361=forever +-1655721430=prayeroff,17 +-1655721431=prayeroff,16 +-1655721432=prayeroff,15 +1959211420=mapfunction,15 +1959211663=mapfunction,90 +1959211421=mapfunction,16 +1959211422=mapfunction,17 +1959211423=mapfunction,18 +303737217=options_icons,4 +303737216=options_icons,3 +303737215=options_icons,2 +-1665005042=funny bunnies +303737214=options_icons,1 +303737219=options_icons,6 +303737218=options_icons,5 +303737213=options_icons,0 +95997798=we are the fairies +2001751835=desert heat +1959211424=mapfunction,19 +-1655721437=prayeroff,10 +687938017=clanwars +-1776024210=desolate_mage +-650944128=strength of saradomin +-1655721433=prayeroff,14 +1160873524=aye car rum ba +-1655721434=prayeroff,13 +-1655721435=prayeroff,12 +-1081314499=marble +-1655721436=prayeroff,11 +1097075475=reset,0 +1959211477=mapfunction,30 +-693313916=warriors guild +3506388=roof +1959211478=mapfunction,31 +1097075476=reset,1 +-2134967800=dagannoth dawn +-985763247=planks +1959211479=mapfunction,32 +1999746381=fenkenstrain's refrain +898010371=garden of winter +359174830=rat hunt +1959211482=mapfunction,35 +686441581=lightness +1959211483=mapfunction,36 +1959211484=mapfunction,37 +1959211485=mapfunction,38 +1959211486=mapfunction,39 +2023201035=dwarf theme +1959211480=mapfunction,33 +1959211481=mapfunction,34 +-1065532022=combatboxes,1 +-1065532021=combatboxes,2 +-1065532020=combatboxes,3 +1867160429=old_tiles +394756979=scape santa +25205919=elfroof2 +-663428071=dangerous way +-1065532023=combatboxes,0 +1959211450=mapfunction,24 +-895939599=spirit +1959211451=mapfunction,25 +1959211452=mapfunction,26 +1959211453=mapfunction,27 +1959211454=mapfunction,28 +1959211455=mapfunction,29 +-275310687=undercurrent +212205923=goblin village +-303898981=faithless +-1381531001=tomb raider +260940912=marzipan +1343267530=backhmid1 +1343267531=backhmid2 +1097468315=horizon +-1655721404=prayeroff,22 +623451622=kourend_the_magnificent +-1655721405=prayeroff,21 +-1655721406=prayeroff,20 +-1655721400=prayeroff,26 +-313384067=p12_full +-1655721401=prayeroff,25 +-1655721402=prayeroff,24 +-1655721403=prayeroff,23 +95848451=dream +1966781751=maws_jaws_claws +-995428255=parade +95734525=method of madness +-1308064877=hitmarks +1030045177=mutant medley +1333034828=blackmark +851641665=davy jones locker +417793574=scrollbar +1346720900=backleft2 +1884768206=magicoff,48 +1884768207=magicoff,49 +1801140808=fangs for the memory +1884768204=magicoff,46 +1345432055=pinball wizard +1884768205=magicoff,47 +-783693496=dance of the undead +1274780903=chompy hunt +465278529=the lost tribe +-1666437481=combaticons3,6 +2032696205=cabin fever +-1666437480=combaticons3,7 +1825640471=borderland +415928477=zeah_mining +1884768202=magicoff,44 +-607599700=prayeroff,0 +1884768203=magicoff,45 +1884768200=magicoff,42 +1884768201=magicoff,43 +-1666437487=combaticons3,0 +-1666437486=combaticons3,1 +813726263=crystal cave +1235442953=pathways +518814479=lullaby +-1666437483=combaticons3,4 +1585007985=magicon2,7 +-1666437482=combaticons3,5 +1585007986=magicon2,8 +-1666437485=combaticons3,2 +1585007987=magicon2,9 +-1666437484=combaticons3,3 +104080482=moody +1969878967=emotes,39 +-665666447=work work work +1364992651=evil bobs island +1969878965=emotes,37 +1227328817=verdana_15pt_regular +1969878966=emotes,38 +1969878963=emotes,35 +1581724013=monkey business +1969878964=emotes,36 +-74307138=miscellania +1969878961=emotes,33 +1969878962=emotes,34 +1969878960=emotes,32 +1131171307=wayward +-1154558416=sl_arrows +529929957=overpass +1258058669=huffman +-694094064=adventure +1171698653=orb_xp,1 +1171698652=orb_xp,0 +1171698655=orb_xp,3 +1171698654=orb_xp,2 +1802171733=arceuus_sigil +221109227=tears of guthix +-1661754893=elfroof +-1666437478=combaticons3,9 +1124565314=warrior +1969878958=emotes,30 +1969878959=emotes,31 +-934797897=reggae +2110260221=the genie +-1666437479=combaticons3,8 +104257585=mummy +-1923924724=sworddecor,0 +2136325196=staticons,17 +-1332194002=background +2136164423=homescape +-1923924721=sworddecor,3 +2136325194=staticons,15 +-1923924722=sworddecor,2 +-873564465=tiptoe +2136325195=staticons,16 +-1923924723=sworddecor,1 +123560953=espionage +2136325192=staticons,13 +2136325193=staticons,14 +1038911415=gnome king +2136325190=staticons,11 +2136325191=staticons,12 +1854274741=karamja jam +1969878989=emotes,40 +-1242708793=glyphs +563269755=the terrible tower +1650323088=twilight +-12868552=sea shanty +289742397=book of spells +1880989696=dragontooth island +2136325189=staticons,10 +110873=pen +-454421102=out of the deep +825919099=options_icons,19 +825919097=options_icons,17 +825919098=options_icons,18 +-1349119470=cursed +1585007978=magicon2,0 +825919095=options_icons,15 +1585007979=magicon2,1 +825919096=options_icons,16 +825919093=options_icons,13 +825919094=options_icons,14 +825919091=options_icons,11 +825919092=options_icons,12 +-895977880=sphinx +-874529881=city of the dead +825919090=options_icons,10 +1585007981=magicon2,3 +1585007982=magicon2,4 +1585007983=magicon2,5 +-1618729246=body parts +1585007984=magicon2,6 +1585007980=magicon2,2 +1086075866=shayzien_sigil +2103661451=jester minute +-911346307=steelborder,2 +-1809781334=button_brown_big +-911346306=steelborder,3 +-816227352=vision +-911346309=steelborder,0 +109407595=shine +-911346308=steelborder,1 +-119954464=combaticons3,12 +-119954465=combaticons3,11 +-1846853118=armageddon +-119954462=combaticons3,14 +-119954463=combaticons3,13 +-119954460=combaticons3,16 +-908183966=scarab +-119954461=combaticons3,15 +-282886672=home sweet home +103666243=march +1969878929=emotes,22 +1643875326=fire and brimstone +1969878927=emotes,20 +-119954466=combaticons3,10 +1969878928=emotes,21 +-839455633=close quarters +941457503=way of the enchanter +-1453405761=mor-ul-rek +-415134015=have a blast +-1658514874=floating free +1213477442=chickened out +-1619800349=emotes_locked,27 +-599680631=fear and loathing +-1081041422=insect queen +-1268786147=forest +-119954459=combaticons3,17 +-119954457=combaticons3,19 +-119954458=combaticons3,18 +-850395529=trouble brewing +-1773920521=cave of the goblins +-771284962=claustrophobia +1310729739=bankbuttons,2 +1306691868=upcoming +1465443077=over to nardah +1310729744=bankbuttons,7 +1310729743=bankbuttons,6 +1310729742=bankbuttons,5 +1234827707=deep wildy +-90350772=xenophobe +-750127868=arabian +1310729741=bankbuttons,4 +1310729740=bankbuttons,3 +1041911129=waterlogged +108875897=runes +1447063382=barb wire +-378865792=magic dance +285466503=overlay_duel +1814287296=zeah_magic +1976894499=down to earth +1969878936=emotes,29 +1969878934=emotes,27 +-1567437308=deadlands +1969878935=emotes,28 +1310729738=bankbuttons,1 +1969878932=emotes,25 +-957019274=too many cooks +1310729737=bankbuttons,0 +2092627105=silence +1969878933=emotes,26 +1969878930=emotes,23 +1969878931=emotes,24 +-901674570=well of voyage