diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..bdb0cabc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..322e5e18 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# eclipse +bin +*.launch +.settings +.metadata +.classpath +.project + +# idea +out +*.ipr +*.iws +*.iml +.idea + +# gradle +build +.gradle + +# other +eclipse +run \ No newline at end of file diff --git a/BUILD.bat b/BUILD.bat new file mode 100644 index 00000000..224c3705 --- /dev/null +++ b/BUILD.bat @@ -0,0 +1,3 @@ +rd /s "./build/classes/main/" +del /s "./build/libs/" +gradlew build \ No newline at end of file diff --git a/README.md b/README.md index ccb2c752..dce1c21d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,8 @@ # Sound-Physics A Minecraft mod that provides realistic sound attenuation, reverberation, and absorption through blocks. + +Changes compared to sonicether/Sound-Physics: + - Updated to 1.12.2 + - Cleaned up whole codebase (compiled binary shrank by a factor of ~4 in file size) + +I am currently not working on this anymore, see https://github.com/djpadbit/Sound-Physics for a fork of this fork that brings some new features! diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..b51e22bf --- /dev/null +++ b/build.gradle @@ -0,0 +1,54 @@ +buildscript { + repositories { + jcenter() + maven { url = "http://files.minecraftforge.net/maven" } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' + } +} +apply plugin: 'net.minecraftforge.gradle.forge' +//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. + +version = "1.12.2" +archivesBaseName = "Sound-Physics" + +jar { + manifest { + attributes 'FMLCorePlugin': 'com.sonicether.soundphysics.CoreModLoader' + attributes 'FMLCorePluginContainsFMLMod': 'true' + } +} + +sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. +compileJava { + sourceCompatibility = targetCompatibility = '1.8' +} + +minecraft { + version = "1.12.2-14.23.0.2542" + runDir = "run" + mappings = "snapshot_20171003" +} + +dependencies { +} + +processResources { + // this will ensure that this task is redone when the versions change. + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version + + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' + + // replace version and mcversion + expand 'version':project.version, 'mcversion':project.minecraft.version + } + + // copy everything else except the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..e9b9fd5a --- /dev/null +++ b/gradle.properties @@ -0,0 +1,3 @@ +# Sets default memory used for gradle commands. Can be overridden by user or command line properties. +# This is required to provide enough memory for the Minecraft decompilation process. +org.gradle.jvmargs=-Xmx3G diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..30d399d8 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 00000000..e18cba72 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Sep 14 12:28:28 PDT 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip diff --git a/gradlew b/gradlew new file mode 100644 index 00000000..91a7e269 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..8a0b282a --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/com/sonicether/soundphysics/ClientProxy.java b/src/main/java/com/sonicether/soundphysics/ClientProxy.java deleted file mode 100644 index 969bb1fd..00000000 --- a/src/main/java/com/sonicether/soundphysics/ClientProxy.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.sonicether.soundphysics; - -import net.minecraftforge.fml.common.event.FMLInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; - -public class ClientProxy extends CommonProxy -{ - @Override - public void preInit(FMLPreInitializationEvent event) - { - super.preInit(event); - } - - @Override - public void init(FMLInitializationEvent event) - { - super.init(event); - } - - @Override - public void postInit(FMLPostInitializationEvent event) - { - super.postInit(event); - } -} diff --git a/src/main/java/com/sonicether/soundphysics/CommonProxy.java b/src/main/java/com/sonicether/soundphysics/CommonProxy.java deleted file mode 100644 index 64dc24e6..00000000 --- a/src/main/java/com/sonicether/soundphysics/CommonProxy.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.sonicether.soundphysics; - -import net.minecraftforge.fml.common.event.FMLInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; - -public class CommonProxy -{ - public void preInit(FMLPreInitializationEvent event) - { - - } - - public void init(FMLInitializationEvent event) - { - - } - - public void postInit(FMLPostInitializationEvent event) - { - - } -} diff --git a/src/main/java/com/sonicether/soundphysics/Config.java b/src/main/java/com/sonicether/soundphysics/Config.java new file mode 100644 index 00000000..045043ae --- /dev/null +++ b/src/main/java/com/sonicether/soundphysics/Config.java @@ -0,0 +1,141 @@ +package com.sonicether.soundphysics; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.config.ConfigElement; +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.fml.client.config.IConfigElement; +import net.minecraftforge.fml.client.event.ConfigChangedEvent; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +public class Config { + + public static final Config instance; + private Configuration forgeConfig; + + // general + public static float rolloffFactor; + public static float globalReverbGain; + public static float globalReverbBrightness; + public static float soundDistanceAllowance; + public static float globalBlockAbsorption; + public static float globalBlockReflectance; + public static float airAbsorption; + public static float underwaterFilter; + + // performance + public static boolean skipRainOcclusionTracing; + public static int environmentEvaluationRays; + public static boolean simplerSharedAirspaceSimulation; + + // block properties + public static float stoneReflectivity; + public static float woodReflectivity; + public static float groundReflectivity; + public static float plantReflectivity; + public static float metalReflectivity; + public static float glassReflectivity; + public static float clothReflectivity; + public static float sandReflectivity; + public static float snowReflectivity; + + private static final String categoryGeneral = "General"; + private static final String categoryPerformance = "Performance"; + private static final String categoryMaterialProperties = "Material properties"; + + static { + instance = new Config(); + } + + private Config() { + } + + public void preInit(final FMLPreInitializationEvent event) { + this.forgeConfig = new Configuration(event.getSuggestedConfigurationFile()); + syncConfig(); + } + + public void init(final FMLInitializationEvent event) { + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void onConfigChanged(final ConfigChangedEvent.OnConfigChangedEvent eventArgs) { + if (eventArgs.getModID().equals(SoundPhysics.modid)) { + syncConfig(); + } + } + + public List getConfigElements() { + final ArrayList list = new ArrayList(); + + list.add(new ConfigElement(this.forgeConfig.getCategory(Config.categoryGeneral))); + list.add(new ConfigElement(this.forgeConfig.getCategory(Config.categoryPerformance))); + list.add(new ConfigElement(this.forgeConfig.getCategory(Config.categoryMaterialProperties))); + + return list; + } + + private void syncConfig() { + // General + rolloffFactor = this.forgeConfig.getFloat("Attenuation Factor", categoryGeneral, 1.0f, 0.2f, 1.0f, + "Affects how quiet a sound gets based on distance. Lower values mean distant sounds are louder. 1.0 is the physically correct value."); + globalReverbGain = this.forgeConfig.getFloat("Global Reverb Gain", categoryGeneral, 1.0f, 0.1f, 2.0f, + "The global volume of simulated reverberations."); + globalReverbBrightness = this.forgeConfig.getFloat("Global Reverb Brightness", categoryGeneral, 1.0f, 0.1f, + 2.0f, + "The brightness of reverberation. Higher values result in more high frequencies in reverberation. Lower values give a more muffled sound to the reverb."); + globalBlockAbsorption = this.forgeConfig.getFloat("Global Block Absorption", categoryGeneral, 1.0f, 0.1f, 4.0f, + "The global amount of sound that will be absorbed when traveling through blocks."); + globalBlockReflectance = this.forgeConfig.getFloat("Global Block Reflectance", categoryGeneral, 1.0f, 0.1f, + 4.0f, + "The global amount of sound reflectance energy of all blocks. Lower values result in more conservative reverb simulation with shorter reverb tails. Higher values result in more generous reverb simulation with higher reverb tails."); + soundDistanceAllowance = this.forgeConfig.getFloat("Sound Distance Allowance", categoryGeneral, 4.0f, 1.0f, + 6.0f, + "Minecraft won't allow sounds to play past a certain distance. This parameter is a multiplier for how far away a sound source is allowed to be in order for it to actually play. Values too high can cause polyphony issues."); + airAbsorption = this.forgeConfig.getFloat("Air Absorption", categoryGeneral, 1.0f, 0.0f, 5.0f, + "A value controlling the amount that air absorbs high frequencies with distance. A value of 1.0 is physically correct for air with normal humidity and temperature. Higher values mean air will absorb more high frequencies with distance. 0 disables this effect."); + underwaterFilter = this.forgeConfig.getFloat("Underwater Filter", categoryGeneral, 0.8f, 0.0f, 1.0f, + "How much sound is filtered when the player is underwater. 0.0 means no filter. 1.0 means fully filtered."); + + // performance + skipRainOcclusionTracing = this.forgeConfig.getBoolean("Skip Rain Occlusion Tracing", categoryPerformance, true, + "If true, rain sound sources won't trace for sound occlusion. This can help performance during rain."); + environmentEvaluationRays = this.forgeConfig.getInt("Environment Evaluation Rays", categoryPerformance, 32, 8, + 64, + "The number of rays to trace to determine reverberation for each sound source. More rays provides more consistent tracing results but takes more time to calculate. Decrease this value if you experience lag spikes when sounds play."); + simplerSharedAirspaceSimulation = this.forgeConfig.getBoolean("Simpler Shared Airspace Simulation", + categoryPerformance, false, + "If true, enables a simpler technique for determining when the player and a sound source share airspace. Might sometimes miss recognizing shared airspace, but it's faster to calculate."); + + // material properties + stoneReflectivity = this.forgeConfig.getFloat("Stone Reflectivity", categoryMaterialProperties, 0.95f, 0.0f, + 1.0f, "Sound reflectivity for stone blocks."); + woodReflectivity = this.forgeConfig.getFloat("Wood Reflectivity", categoryMaterialProperties, 0.7f, 0.0f, 1.0f, + "Sound reflectivity for wooden blocks."); + groundReflectivity = this.forgeConfig.getFloat("Ground Reflectivity", categoryMaterialProperties, 0.3f, 0.0f, + 1.0f, "Sound reflectivity for ground blocks (dirt, gravel, etc)."); + plantReflectivity = this.forgeConfig.getFloat("Foliage Reflectivity", categoryMaterialProperties, 0.2f, 0.0f, + 1.0f, "Sound reflectivity for foliage blocks (leaves, grass, etc.)."); + metalReflectivity = this.forgeConfig.getFloat("Metal Reflectivity", categoryMaterialProperties, 0.97f, 0.0f, + 1.0f, "Sound reflectivity for metal blocks."); + glassReflectivity = this.forgeConfig.getFloat("Glass Reflectivity", categoryMaterialProperties, 0.5f, 0.0f, + 1.0f, "Sound reflectivity for glass blocks."); + clothReflectivity = this.forgeConfig.getFloat("Cloth Reflectivity", categoryMaterialProperties, 0.25f, 0.0f, + 1.0f, "Sound reflectivity for cloth blocks (carpet, wool, etc)."); + sandReflectivity = this.forgeConfig.getFloat("Sand Reflectivity", categoryMaterialProperties, 0.2f, 0.0f, 1.0f, + "Sound reflectivity for sand blocks."); + snowReflectivity = this.forgeConfig.getFloat("Snow Reflectivity", categoryMaterialProperties, 0.2f, 0.0f, 1.0f, + "Sound reflectivity for snow blocks."); + + if (this.forgeConfig.hasChanged()) { + this.forgeConfig.save(); + SoundPhysics.applyConfigChanges(); + } + } + +} diff --git a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java new file mode 100644 index 00000000..76153951 --- /dev/null +++ b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java @@ -0,0 +1,243 @@ +package com.sonicether.soundphysics; + +import java.util.Iterator; +import java.util.ListIterator; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.VarInsnNode; + +import net.minecraft.launchwrapper.IClassTransformer; + +public class CoreModInjector implements IClassTransformer { + + @Override + public byte[] transform(final String obfuscated, final String deobfuscated, byte[] bytes) { + if (obfuscated.equals("chm$a")) { + // Inside SoundManager.SoundSystemStarterThread + InsnList toInject = new InsnList(); + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "init", + "()V", false)); + + // Target method: Constructor + bytes = patchMethodInClass(obfuscated, bytes, "", "(Lchm;)V", Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, "", null, toInject, false, 0, 0, false, 0); + } else + + if (obfuscated.equals("chm")) { + // Inside SoundManager + InsnList toInject = new InsnList(); + + toInject.add(new VarInsnNode(Opcodes.ALOAD, 7)); + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", + "setLastSoundCategory", "(Lqg;)V", false)); + + // Target method: playSound + bytes = patchMethodInClass(obfuscated, bytes, "c", "(Lcgt;)V", Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, "setVolume", null, toInject, false, 0, 0, false, 0); + + toInject = new InsnList(); + toInject.add(new VarInsnNode(Opcodes.ALOAD, 1)); + toInject.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "cgt", "a", "()Lnf;", true)); + toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "nf", "toString", "()Ljava/lang/String;", false)); + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", + "setLastSoundName", "(Ljava/lang/String;)V", false)); + + // Target method: playSound + bytes = patchMethodInClass(obfuscated, bytes, "c", "(Lcgt;)V", Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, "setVolume", null, toInject, false, 0, 0, false, 0); + + toInject = new InsnList(); + toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", + "globalVolumeMultiplier", "F")); + toInject.add(new InsnNode(Opcodes.FMUL)); + + // Target method: playSound, target invocation getClampedVolume + bytes = patchMethodInClass(obfuscated, bytes, "c", "(Lcgt;)V", Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, "e", "(Lcgt;)F", toInject, false, 0, 0, false, 0); + } else + + if (obfuscated.equals("paulscode.sound.libraries.SourceLWJGLOpenAL")) { + // Inside SourceLWJGLOpenAL + InsnList toInject = new InsnList(); + + toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); + toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", + "Lpaulscode/sound/Vector3D;")); + toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/Vector3D", "x", "F")); + toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); + toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", + "Lpaulscode/sound/Vector3D;")); + toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/Vector3D", "y", "F")); + toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); + toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", + "Lpaulscode/sound/Vector3D;")); + toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/Vector3D", "z", "F")); + toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); + toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/SourceLWJGLOpenAL", + "channelOpenAL", "Lpaulscode/sound/libraries/ChannelLWJGLOpenAL;")); + toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/ChannelLWJGLOpenAL", "ALSource", + "Ljava/nio/IntBuffer;")); + toInject.add(new InsnNode(Opcodes.ICONST_0)); + toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/nio/IntBuffer", "get", "(I)I", false)); + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", + "onPlaySound", "(FFFI)V", false)); + + // Target method: play + bytes = patchMethodInClass(obfuscated, bytes, "play", "(Lpaulscode/sound/Channel;)V", Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, "play", null, toInject, false, 0, 0, false, 0); + } else + + if (obfuscated.equals("paulscode.sound.SoundSystem")) { + // Inside SoundSystem + InsnList toInject = new InsnList(); + + toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", + "attenuationModel", "I")); + toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", + "globalRolloffFactor", "F")); + + // Target method: newSource + bytes = patchMethodInClass(obfuscated, bytes, "newSource", + "(ZLjava/lang/String;Ljava/net/URL;Ljava/lang/String;ZFFFIF)V", Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, "", null, toInject, true, 2, 0, false, 0); + } else + + if (obfuscated.equals("pl")) { + // Inside PlayerList + InsnList toInject = new InsnList(); + + // Multiply sound distance volume play decision by + // SoundPhysics.soundDistanceAllowance + toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", + "soundDistanceAllowance", "D")); + toInject.add(new InsnNode(Opcodes.DMUL)); + + // Target method: sendToAllNearExcept + bytes = patchMethodInClass(obfuscated, bytes, "a", "(Laed;DDDDILht;)V", Opcodes.DCMPG, + AbstractInsnNode.INSN, "", "", toInject, true, 0, 0, false, 0); + } else + + if (obfuscated.equals("vg")) { + // Inside Entity + InsnList toInject = new InsnList(); + + // Offset entity sound by their eye height + toInject.add(new VarInsnNode(Opcodes.ALOAD, 1)); + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", + "calculateEntitySoundOffset", "(Lvg;Lqe;)D", false)); + toInject.add(new InsnNode(Opcodes.DADD)); + toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); + + // Target method: playSound + // Inside target method, target node: Entity/getSoundCategory + bytes = patchMethodInClass(obfuscated, bytes, "a", "(Lqe;FF)V", Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, "bK", null, toInject, true, 0, 0, false, -3); + } + + return bytes; + } + + private byte[] patchMethodInClass(String className, final byte[] bytes, final String targetMethod, + final String targetMethodSignature, final int targetNodeOpcode, final int targetNodeType, + final String targetInvocationMethodName, final String targetInvocationMethodSignature, + final InsnList instructionsToInject, final boolean insertBefore, final int nodesToDeleteBefore, + final int nodesToDeleteAfter, final boolean deleteTargetNode, final int targetNodeOffset) { + + final ClassNode classNode = new ClassNode(); + final ClassReader classReader = new ClassReader(bytes); + classReader.accept(classNode, 0); + final Iterator methodIterator = classNode.methods.iterator(); + + while (methodIterator.hasNext()) { + final MethodNode m = methodIterator.next(); + + if (m.name.equals(targetMethod) && m.desc.equals(targetMethodSignature)) { + + AbstractInsnNode targetNode = null; + + final ListIterator nodeIterator = m.instructions.iterator(); + while (nodeIterator.hasNext()) { + AbstractInsnNode currentNode = nodeIterator.next(); + + if (currentNode.getOpcode() == targetNodeOpcode) { + + if (targetNodeType == AbstractInsnNode.METHOD_INSN) { + if (currentNode.getType() == AbstractInsnNode.METHOD_INSN) { + final MethodInsnNode method = (MethodInsnNode) currentNode; + if (method.name.equals(targetInvocationMethodName)) { + if (method.desc.equals(targetInvocationMethodSignature) + || targetInvocationMethodSignature == null) { + targetNode = currentNode; + // Due to collisions, do not put break + // statements here! + } + + } + } + } else { + if (currentNode.getType() == targetNodeType) { + targetNode = currentNode; + // Due to collisions, do not put break + // statements here! + } + } + + } + } + + if (targetNode == null) { + SoundPhysics.logError("Target node not found!" + className); + break; + } + + // Offset the target node by the supplied offset value + if (targetNodeOffset > 0) { + for (int i = 0; i < targetNodeOffset; i++) { + targetNode = targetNode.getNext(); + } + } else if (targetNodeOffset < 0) { + for (int i = 0; i < -targetNodeOffset; i++) { + targetNode = targetNode.getPrevious(); + } + } + + // If we've found the target, inject the instructions! + for (int i = 0; i < nodesToDeleteBefore; i++) { + final AbstractInsnNode previousNode = targetNode.getPrevious(); + m.instructions.remove(previousNode); + } + + for (int i = 0; i < nodesToDeleteAfter; i++) { + final AbstractInsnNode nextNode = targetNode.getNext(); + m.instructions.remove(nextNode); + } + + if (insertBefore) { + m.instructions.insertBefore(targetNode, instructionsToInject); + } else { + m.instructions.insert(targetNode, instructionsToInject); + } + + if (deleteTargetNode) { + m.instructions.remove(targetNode); + } + + break; + } + } + + final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); + classNode.accept(writer); + return writer.toByteArray(); + } + +} diff --git a/src/main/java/com/sonicether/soundphysics/CoreModLoader.java b/src/main/java/com/sonicether/soundphysics/CoreModLoader.java new file mode 100644 index 00000000..0f2f40ec --- /dev/null +++ b/src/main/java/com/sonicether/soundphysics/CoreModLoader.java @@ -0,0 +1,35 @@ +package com.sonicether.soundphysics; + +import java.util.Map; + +import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; +import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.MCVersion; + +@MCVersion(value = SoundPhysics.mcVersion) +public class CoreModLoader implements IFMLLoadingPlugin { + + @Override + public String[] getASMTransformerClass() { + return new String[] { CoreModInjector.class.getName() }; + } + + @Override + public String getModContainerClass() { + return null; + } + + @Override + public String getSetupClass() { + return null; + } + + @Override + public void injectData(final Map data) { + } + + @Override + public String getAccessTransformerClass() { + return null; + } + +} diff --git a/src/main/java/com/sonicether/soundphysics/Int3.java b/src/main/java/com/sonicether/soundphysics/Int3.java deleted file mode 100644 index c8af31e1..00000000 --- a/src/main/java/com/sonicether/soundphysics/Int3.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.sonicether.soundphysics; - -public class Int3 -{ - public int x; - public int y; - public int z; - - public static Int3 create(int x, int y, int z) - { - Int3 i = new Int3(); - - i.x = x; - i.y = y; - i.z = z; - - return i; - } - - @Override public boolean equals(Object b) - { - Int3 i = (Int3)b; - return (this.x == i.x && this.y == i.y && this.z == i.z); - } - - Int3() - { - - } -} diff --git a/src/main/java/com/sonicether/soundphysics/ModSoundPhysics.java b/src/main/java/com/sonicether/soundphysics/ModSoundPhysics.java deleted file mode 100644 index 68f9678a..00000000 --- a/src/main/java/com/sonicether/soundphysics/ModSoundPhysics.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.sonicether.soundphysics; - - -/* -import cpw.mods.fml.common.Mod; -import cpw.mods.fml.common.Mod.EventHandler; -import cpw.mods.fml.common.SidedProxy; -import cpw.mods.fml.common.event.FMLInitializationEvent; -import cpw.mods.fml.common.event.FMLPostInitializationEvent; -import cpw.mods.fml.common.event.FMLPreInitializationEvent; - -@Mod(modid = ModSoundPhysics.MODID, version = ModSoundPhysics.VERSION) -public class ModSoundPhysics -{ - public static final String MODID = "soundphysics"; - public static final String VERSION = "1.0"; - - @SidedProxy(clientSide="com.sonicether.soundphysics.ClientProxy", serverSide="com.sonicether.soundphysics.ServerProxy") - public static CommonProxy proxy; - - @EventHandler - public void preInit(FMLPreInitializationEvent event) - { - - proxy.preInit(event); - } - - @EventHandler - public void init(FMLInitializationEvent event) - { - proxy.init(event); - } - - @EventHandler - public void postInit(FMLPostInitializationEvent event) - { - proxy.postInit(event); - } -} -*/ - - -public class ModSoundPhysics -{ - -} \ No newline at end of file diff --git a/src/main/java/com/sonicether/soundphysics/ReverbParams.java b/src/main/java/com/sonicether/soundphysics/ReverbParams.java index 0d6d2fee..97f269f0 100644 --- a/src/main/java/com/sonicether/soundphysics/ReverbParams.java +++ b/src/main/java/com/sonicether/soundphysics/ReverbParams.java @@ -1,100 +1,90 @@ package com.sonicether.soundphysics; -import org.lwjgl.openal.EFX10; +public class ReverbParams { -public class ReverbParams -{ - public float decayTime; // min: 0.1f max: 10.0f - public float density; // min: 0.0f max: 1.0f - public float diffusion; // min: 0.0f max: 1.0f - public float gain; // min: 0.0f max: 1.0f - public float gainHF; // min: 0.0f max: 1.0f - public float decayHFRatio; // min: 0.1f max: 2.0f - public float reflectionsGain; // min: 0.1f max: 3.16f - public float reflectionsDelay; // min: 0.0f max: 0.3f - public float lateReverbGain; // min: 0.0f max: 10.0f - public float lateReverbDelay; // min: 0.0f max: 0.1f - public float airAbsorptionGainHF; // min: 0.892f max: 1.0f - public float roomRolloffFactor; // min: 0.0f max: 10.0f - - public static ReverbParams getReverb0() - { - ReverbParams r = new ReverbParams(); + public float decayTime; // min: 0.1f max: 10.0f + public float density; // min: 0.0f max: 1.0f + public float diffusion; // min: 0.0f max: 1.0f + public float gain; // min: 0.0f max: 1.0f + public float gainHF; // min: 0.0f max: 1.0f + public float decayHFRatio; // min: 0.1f max: 2.0f + public float reflectionsGain; // min: 0.1f max: 3.16f + public float reflectionsDelay; // min: 0.0f max: 0.3f + public float lateReverbGain; // min: 0.0f max: 10.0f + public float lateReverbDelay; // min: 0.0f max: 0.1f + public float airAbsorptionGainHF; // min: 0.892f max: 1.0f + public float roomRolloffFactor; // min: 0.0f max: 10.0f + + public static ReverbParams getReverb0() { + final ReverbParams r = new ReverbParams(); r.decayTime = 0.15f; r.density = 0.0f; r.diffusion = 1.0f; r.gain = 0.2f * SoundPhysics.globalReverbMultiplier * 0.85f; r.gainHF = 0.99f; - r.decayHFRatio = 0.6f * SoundPhysicsCore.Config.globalReverbBrightness; + r.decayHFRatio = 0.6f * Config.globalReverbBrightness; r.reflectionsGain = 2.5f; r.reflectionsDelay = 0.001f; r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.011f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.16f * SoundPhysicsCore.Config.rolloffFactor; - + r.roomRolloffFactor = 0.16f * Config.rolloffFactor; + return r; } - - public static ReverbParams getReverb1() - { - ReverbParams r = new ReverbParams(); + + public static ReverbParams getReverb1() { + final ReverbParams r = new ReverbParams(); r.decayTime = 0.55f; r.density = 0.0f; r.diffusion = 1.0f; r.gain = 0.3f * SoundPhysics.globalReverbMultiplier * 0.85f; r.gainHF = 0.99f; - r.decayHFRatio = 0.7f * SoundPhysicsCore.Config.globalReverbBrightness; + r.decayHFRatio = 0.7f * Config.globalReverbBrightness; r.reflectionsGain = 0.2f; r.reflectionsDelay = 0.015f; r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.011f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.15f * SoundPhysicsCore.Config.rolloffFactor; - + r.roomRolloffFactor = 0.15f * Config.rolloffFactor; + return r; } - - public static ReverbParams getReverb2() - { - ReverbParams r = new ReverbParams(); + + public static ReverbParams getReverb2() { + final ReverbParams r = new ReverbParams(); r.decayTime = 1.68f; r.density = 0.1f; r.diffusion = 1.0f; r.gain = 0.5f * SoundPhysics.globalReverbMultiplier * 0.85f; r.gainHF = 0.99f; - r.decayHFRatio = 0.7f * SoundPhysicsCore.Config.globalReverbBrightness; + r.decayHFRatio = 0.7f * Config.globalReverbBrightness; r.reflectionsGain = 0.0f; r.reflectionsDelay = 0.021f; r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.021f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.13f * SoundPhysicsCore.Config.rolloffFactor; - + r.roomRolloffFactor = 0.13f * Config.rolloffFactor; + return r; } - - public static ReverbParams getReverb3() - { - ReverbParams r = new ReverbParams(); + + public static ReverbParams getReverb3() { + final ReverbParams r = new ReverbParams(); r.decayTime = 4.142f; r.density = 0.5f; r.diffusion = 1.0f; r.gain = 0.4f * SoundPhysics.globalReverbMultiplier * 0.85f; r.gainHF = 0.89f; - r.decayHFRatio = 0.7f * SoundPhysicsCore.Config.globalReverbBrightness; + r.decayHFRatio = 0.7f * Config.globalReverbBrightness; r.reflectionsGain = 0.0f; r.reflectionsDelay = 0.025f; r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.021f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.11f * SoundPhysicsCore.Config.rolloffFactor; - + r.roomRolloffFactor = 0.11f * Config.rolloffFactor; + return r; } - - ReverbParams() - { - - } + } diff --git a/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java b/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java deleted file mode 100644 index c5f37193..00000000 --- a/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.sonicether.soundphysics; - -import java.util.ArrayList; -import java.util.List; - -import net.minecraft.client.gui.GuiScreen; -import net.minecraftforge.common.config.Config; -import net.minecraftforge.common.config.ConfigElement; -import net.minecraftforge.common.config.Configuration; -import net.minecraftforge.fml.client.config.DummyConfigElement; -//import cpw.mods.fml.client.config.GuiConfig; -import net.minecraftforge.fml.client.config.GuiConfig; -import net.minecraftforge.fml.client.config.IConfigElement; - -public class SPConfigGUI extends GuiConfig -{ - public SPConfigGUI(GuiScreen parent) - { - super(parent, getConfigElements(), SoundPhysicsCore.modid, false, false, "Sound Physics Configuration"); - } - - /** Compiles a list of config elements */ - private static List getConfigElements() - { - List list = new ArrayList(); - - //Add categories to config GUI - list.add(categoryElement(SoundPhysicsCore.configFile.CATEGORY_GENERAL, "General", "soundphysics.configgui.ctgy.general")); - list.add(categoryElement(SoundPhysicsCore.Config.categoryPerformance, "Performance", "soundphysics.configgui.ctgy.performance")); - list.add(categoryElement(SoundPhysicsCore.Config.categoryMaterialProperties, "Material Properties", "soundphysics.configgui.ctgy.materialProperties")); - list.add(categoryElement(SoundPhysicsCore.Config.categoryMisc, "Misc", "soundphysics.configgui.ctgy.misc")); - - return list; - } - - /** Creates a button linking to another screen where all options of the category are available */ - private static IConfigElement categoryElement(String category, String name, String tooltip_key) - { - return new DummyConfigElement.DummyCategoryElement(name, tooltip_key, - new ConfigElement(SoundPhysicsCore.configFile.getCategory(category)).getChildElements()); - } -} \ No newline at end of file diff --git a/src/main/java/com/sonicether/soundphysics/SPDummyContainer.java b/src/main/java/com/sonicether/soundphysics/SPDummyContainer.java deleted file mode 100644 index 1e2621d8..00000000 --- a/src/main/java/com/sonicether/soundphysics/SPDummyContainer.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.sonicether.soundphysics; - -import com.google.common.collect.Lists; -import com.google.common.eventbus.EventBus; -import com.google.common.eventbus.Subscribe; - -import net.minecraftforge.fml.common.DummyModContainer; -import net.minecraftforge.fml.common.LoadController; -import net.minecraftforge.fml.common.ModMetadata; -import net.minecraftforge.fml.common.event.FMLConstructionEvent; -import net.minecraftforge.fml.common.event.FMLInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; -/* -import cpw.mods.fml.common.DummyModContainer; -import cpw.mods.fml.common.LoadController; -import cpw.mods.fml.common.ModMetadata; -import cpw.mods.fml.common.event.FMLConstructionEvent; -import cpw.mods.fml.common.event.FMLInitializationEvent; -import cpw.mods.fml.common.event.FMLPostInitializationEvent; -import cpw.mods.fml.common.event.FMLPreInitializationEvent; -*/ - -public class SPDummyContainer extends DummyModContainer -{ - public SPDummyContainer() - { - super(new ModMetadata()); - ModMetadata meta = getMetadata(); - meta.modId = "SoundPhysics"; - meta.name = "Sound Physics"; - meta.version = "@VERSION@"; - meta.credits = "Manoog"; - meta.authorList = Lists.newArrayList(); - meta.authorList.add("sonicether"); - meta.description = "Adds realistic sound attenuation, obstruction, and reverberation."; - meta.url = ""; // TODO: Update this! - meta.updateUrl = ""; - meta.screenshots = new String[0]; - meta.logoFile = ""; - } - - @Override - public boolean registerBus(EventBus bus, LoadController controller) - { - bus.register(this); - return true; - } - - @Subscribe - public void modConstruction(FMLConstructionEvent event) - { - - } - - @Subscribe - public void init(FMLInitializationEvent event) - { - - } - - @Subscribe - public void preInit(FMLPreInitializationEvent event) - { - - } - - @Subscribe - public void postInit(FMLPostInitializationEvent event) - { - - } -} diff --git a/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java b/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java deleted file mode 100644 index a3824d43..00000000 --- a/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.sonicether.soundphysics; - -import java.util.Map; - -import net.minecraftforge.fml.relauncher.IFMLCallHook; -import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; -import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.MCVersion; - - - -@MCVersion(value="1.11") -public class SPFMLLoadingPlugin implements IFMLLoadingPlugin, IFMLCallHook -{ - - @Override - public String[] getASMTransformerClass() - { - return new String[]{SoundPhysicsCore.class.getName()}; - } - - @Override - public String getModContainerClass() { - //return SPDummyContainer.class.getName(); - return null; - } - - @Override - public String getSetupClass() { - return this.getClass().getName(); - } - - @Override - public void injectData(Map data) { - // TODO Auto-generated method stub - - } - - @Override - public String getAccessTransformerClass() { - // TODO Auto-generated method stub - return null; - } - - // This is the method that FML calls in the main thread before Minecraft - // begins loading. - @Override - public Void call() throws Exception { - // This method is called directly after FML injects the data in the method below. - // TODO Auto-generated method stub - return null; - } - -} diff --git a/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java b/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java deleted file mode 100644 index 66a8646a..00000000 --- a/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.sonicether.soundphysics; - -import java.util.Set; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiScreen; -import net.minecraftforge.fml.client.IModGuiFactory; -import net.minecraftforge.fml.client.IModGuiFactory.RuntimeOptionCategoryElement; -import net.minecraftforge.fml.client.IModGuiFactory.RuntimeOptionGuiHandler; - - -public class SPGUIFactory implements IModGuiFactory -{ - - @Override - public void initialize(Minecraft minecraftInstance) { - // TODO Auto-generated method stub - - } - - @Override - public Class mainConfigGuiClass() { - return SPConfigGUI.class; - } - - @Override - public Set runtimeGuiCategories() { - // TODO Auto-generated method stub - return null; - } - - @Override - public RuntimeOptionGuiHandler getHandlerFor( - RuntimeOptionCategoryElement element) { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/src/main/java/com/sonicether/soundphysics/SPGuiConfig.java b/src/main/java/com/sonicether/soundphysics/SPGuiConfig.java new file mode 100644 index 00000000..58164a52 --- /dev/null +++ b/src/main/java/com/sonicether/soundphysics/SPGuiConfig.java @@ -0,0 +1,13 @@ +package com.sonicether.soundphysics; + +import net.minecraft.client.gui.GuiScreen; +import net.minecraftforge.fml.client.config.GuiConfig; + +public class SPGuiConfig extends GuiConfig { + + public SPGuiConfig(final GuiScreen parent) { + super(parent, Config.instance.getConfigElements(), SoundPhysics.modid, false, false, + "Sound Physics Configuration"); + } + +} \ No newline at end of file diff --git a/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java b/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java new file mode 100644 index 00000000..2e105b82 --- /dev/null +++ b/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java @@ -0,0 +1,30 @@ +package com.sonicether.soundphysics; + +import java.util.Set; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraftforge.fml.client.IModGuiFactory; + +public class SPGuiFactory implements IModGuiFactory { + + @Override + public void initialize(Minecraft minecraftInstance) { + } + + @Override + public boolean hasConfigGui() { + return true; + } + + @Override + public GuiScreen createConfigGui(GuiScreen parentScreen) { + return new SPGuiConfig(parentScreen); + } + + @Override + public Set runtimeGuiCategories() { + return null; + } + +} diff --git a/src/main/java/com/sonicether/soundphysics/ServerProxy.java b/src/main/java/com/sonicether/soundphysics/ServerProxy.java deleted file mode 100644 index d8e0c948..00000000 --- a/src/main/java/com/sonicether/soundphysics/ServerProxy.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.sonicether.soundphysics; - -import net.minecraftforge.fml.common.event.FMLInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; - -public class ServerProxy extends CommonProxy -{ - @Override - public void preInit(FMLPreInitializationEvent event) { - super.preInit(event); - } - - @Override - public void init(FMLInitializationEvent event) { - super.init(event); - } - - @Override - public void postInit(FMLPostInitializationEvent event) { - super.postInit(event); - } -} diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 2eb8f5b9..57a41b1b 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -1,18 +1,19 @@ package com.sonicether.soundphysics; -import java.nio.ByteBuffer; -import java.nio.IntBuffer; -import java.util.ArrayList; +import java.util.regex.Pattern; + +import org.lwjgl.openal.AL10; +import org.lwjgl.openal.AL11; +import org.lwjgl.openal.ALC10; +import org.lwjgl.openal.ALCcontext; +import org.lwjgl.openal.ALCdevice; +import org.lwjgl.openal.EFX10; import net.minecraft.block.Block; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; -//import net.minecraft.client.audio.SoundCategory; -//import net.minecraft.util.MathHelper; -//import net.minecraft.util.MovingObjectPosition; -//import net.minecraft.util.Vec3d; import net.minecraft.util.EnumFacing; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; @@ -20,20 +21,32 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.Vec3i; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import paulscode.sound.SoundSystemConfig; -import org.lwjgl.openal.AL10; -import org.lwjgl.openal.AL11; -import org.lwjgl.openal.ALC10; -import org.lwjgl.openal.ALCcontext; -import org.lwjgl.openal.ALCdevice; -import org.lwjgl.openal.EFX10; +@Mod(modid = SoundPhysics.modid, clientSideOnly = true, acceptedMinecraftVersions = SoundPhysics.mcVersion, version = SoundPhysics.version, guiFactory = "com.sonicether.soundphysics.SPGuiFactory") +public class SoundPhysics { -import paulscode.sound.SoundSystemConfig; + public static final String modid = "soundphysics"; + public static final String version = "1.0.4"; + public static final String mcVersion = "1.12.2"; + + private static final Pattern rainPattern = Pattern.compile(".*rain.*"); + private static final Pattern stepPattern = Pattern.compile(".*step.*"); + private static final Pattern blockPattern = Pattern.compile(".*block.*"); + + @Mod.EventHandler + public void preInit(final FMLPreInitializationEvent event) { + Config.instance.preInit(event); + } + + @Mod.EventHandler + public void init(final FMLInitializationEvent event) { + Config.instance.init(event); + } -public class SoundPhysics -{ - //Private fields private static final String logPrefix = "[SOUND PHYSICS]"; private static int auxFXSlot0; private static int auxFXSlot1; @@ -48,933 +61,580 @@ public class SoundPhysics private static int sendFilter1; private static int sendFilter2; private static int sendFilter3; - + private static Minecraft mc; - + private static SoundCategory lastSoundCategory; private static String lastSoundName; - - - //Public fields + + // THESE VARIABLES ARE CONSTANTLY ACCESSED AND USED BY ASM INJECTED CODE! DO + // NOT REMOVE! public static int attenuationModel = SoundSystemConfig.ATTENUATION_ROLLOFF; - public static float globalRolloffFactor = SoundPhysicsCore.Config.rolloffFactor; + public static float globalRolloffFactor = Config.rolloffFactor; public static float globalVolumeMultiplier = 4.0f; - public static float globalReverbMultiplier = 0.7f * SoundPhysicsCore.Config.globalReverbGain; - public static double soundDistanceAllowance = SoundPhysicsCore.Config.soundDistanceAllowance; - - - - - - public static void init() - { - log("Initializing Sound Physics..."); + public static float globalReverbMultiplier = 0.7f * Config.globalReverbGain; + public static double soundDistanceAllowance = Config.soundDistanceAllowance; + + /** + * CALLED BY ASM INJECTED CODE! + */ + public static void init() { setupEFX(); mc = Minecraft.getMinecraft(); } - - - public static void applyConfigChanges() - { - globalRolloffFactor = SoundPhysicsCore.Config.rolloffFactor; - globalReverbMultiplier = 0.7f * SoundPhysicsCore.Config.globalReverbGain; - soundDistanceAllowance = SoundPhysicsCore.Config.soundDistanceAllowance; - - if (auxFXSlot0 != 0) - { - setReverbParams(ReverbParams.getReverb0(), auxFXSlot0, reverb0); //Set the global reverb parameters and apply them to the effect and effectslot - setReverbParams(ReverbParams.getReverb1(), auxFXSlot1, reverb1); //Set the global reverb parameters and apply them to the effect and effectslot - setReverbParams(ReverbParams.getReverb2(), auxFXSlot2, reverb2); //Set the global reverb parameters and apply them to the effect and effectslot - setReverbParams(ReverbParams.getReverb3(), auxFXSlot3, reverb3); //Set the global reverb parameters and apply them to the effect and effectslot + + public static void applyConfigChanges() { + globalRolloffFactor = Config.rolloffFactor; + globalReverbMultiplier = 0.7f * Config.globalReverbGain; + soundDistanceAllowance = Config.soundDistanceAllowance; + + if (auxFXSlot0 != 0) { + // Set the global reverb parameters and apply them to the effect and + // effectslot + setReverbParams(ReverbParams.getReverb0(), auxFXSlot0, reverb0); + setReverbParams(ReverbParams.getReverb1(), auxFXSlot1, reverb1); + setReverbParams(ReverbParams.getReverb2(), auxFXSlot2, reverb2); + setReverbParams(ReverbParams.getReverb3(), auxFXSlot3, reverb3); } - - } - - - private static int alcGetInt(ALCdevice device, int pname) - { - ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4); - IntBuffer intBuffer = byteBuffer.asIntBuffer(); - - //ALC10.alcGetInteger(device, pname, intBuffer); - - return intBuffer.get(0); } - private static void setupEFX() - { - //Get current context and device - ALCcontext currentContext = ALC10.alcGetCurrentContext(); - ALCdevice currentDevice = ALC10.alcGetContextsDevice(currentContext); - - if (ALC10.alcIsExtensionPresent(currentDevice, "ALC_EXT_EFX")) - { + private static void setupEFX() { + // Get current context and device + final ALCcontext currentContext = ALC10.alcGetCurrentContext(); + final ALCdevice currentDevice = ALC10.alcGetContextsDevice(currentContext); + + if (ALC10.alcIsExtensionPresent(currentDevice, "ALC_EXT_EFX")) { log("EFX Extension recognized."); - } - else - { + } else { logError("EFX Extension not found on current device. Aborting."); return; } - - //Create auxiliary effect slots + + // Create auxiliary effect slots auxFXSlot0 = EFX10.alGenAuxiliaryEffectSlots(); log("Aux slot " + auxFXSlot0 + " created"); EFX10.alAuxiliaryEffectSloti(auxFXSlot0, EFX10.AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, AL10.AL_TRUE); - + auxFXSlot1 = EFX10.alGenAuxiliaryEffectSlots(); log("Aux slot " + auxFXSlot1 + " created"); EFX10.alAuxiliaryEffectSloti(auxFXSlot1, EFX10.AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, AL10.AL_TRUE); - + auxFXSlot2 = EFX10.alGenAuxiliaryEffectSlots(); log("Aux slot " + auxFXSlot2 + " created"); EFX10.alAuxiliaryEffectSloti(auxFXSlot2, EFX10.AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, AL10.AL_TRUE); - + auxFXSlot3 = EFX10.alGenAuxiliaryEffectSlots(); log("Aux slot " + auxFXSlot3 + " created"); - EFX10.alAuxiliaryEffectSloti(auxFXSlot3, EFX10.AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, AL10.AL_TRUE); + EFX10.alAuxiliaryEffectSloti(auxFXSlot3, EFX10.AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, AL10.AL_TRUE); checkErrorLog("Failed creating auxiliary effect slots!"); - - - //Create effect objects - reverb0 = EFX10.alGenEffects(); //Create effect object - EFX10.alEffecti(reverb0, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_EAXREVERB); //Set effect object to be reverb + + reverb0 = EFX10.alGenEffects(); + EFX10.alEffecti(reverb0, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_EAXREVERB); checkErrorLog("Failed creating reverb effect slot 0!"); - reverb1 = EFX10.alGenEffects(); //Create effect object - EFX10.alEffecti(reverb1, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_EAXREVERB); //Set effect object to be reverb + reverb1 = EFX10.alGenEffects(); + EFX10.alEffecti(reverb1, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_EAXREVERB); checkErrorLog("Failed creating reverb effect slot 1!"); - reverb2 = EFX10.alGenEffects(); //Create effect object - EFX10.alEffecti(reverb2, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_EAXREVERB); //Set effect object to be reverb + reverb2 = EFX10.alGenEffects(); + EFX10.alEffecti(reverb2, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_EAXREVERB); checkErrorLog("Failed creating reverb effect slot 2!"); - reverb3 = EFX10.alGenEffects(); //Create effect object - EFX10.alEffecti(reverb3, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_EAXREVERB); //Set effect object to be reverb + reverb3 = EFX10.alGenEffects(); + EFX10.alEffecti(reverb3, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_EAXREVERB); checkErrorLog("Failed creating reverb effect slot 3!"); - - //Create filters + + // Create filters directFilter0 = EFX10.alGenFilters(); EFX10.alFilteri(directFilter0, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS); - + sendFilter0 = EFX10.alGenFilters(); EFX10.alFilteri(sendFilter0, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS); - + sendFilter1 = EFX10.alGenFilters(); EFX10.alFilteri(sendFilter1, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS); - + sendFilter2 = EFX10.alGenFilters(); EFX10.alFilteri(sendFilter2, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS); - + sendFilter3 = EFX10.alGenFilters(); EFX10.alFilteri(sendFilter3, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS); checkErrorLog("Error creating lowpass filters!"); - + applyConfigChanges(); - - //setReverbParams(ReverbParams.getReverb0(), auxFXSlot0, reverb0); //Set the global reverb parameters and apply them to the effect and effectslot - //setReverbParams(ReverbParams.getReverb1(), auxFXSlot1, reverb1); //Set the global reverb parameters and apply them to the effect and effectslot - //setReverbParams(ReverbParams.getReverb2(), auxFXSlot2, reverb2); //Set the global reverb parameters and apply them to the effect and effectslot - //setReverbParams(ReverbParams.getReverb3(), auxFXSlot3, reverb3); //Set the global reverb parameters and apply them to the effect and effectslot } - - public static void setLastSoundCategory(SoundCategory sc) - { - //log("Set last sound category"); + + /** + * CALLED BY ASM INJECTED CODE! + */ + public static void setLastSoundCategory(final SoundCategory sc) { lastSoundCategory = sc; } - - public static void setLastSoundName(String name) - { - //log("Set last sound name: " + name); + + /** + * CALLED BY ASM INJECTED CODE! + */ + public static void setLastSoundName(final String name) { lastSoundName = name; } - - public static void onPlaySound(float posX, float posY, float posZ, int sourceID) - { - //log("On play sound"); - logGeneral("On play sound... Sounrce ID: " + sourceID + " " + posX + ", " + posY + ", " + posZ + " Sound category: " + lastSoundCategory.toString() + " Sound name: " + lastSoundName); - - //Set source to send to reverb - //EFX10.alFilterf(sendFilter0, EFX10.AL_LOWPASS_GAINHF, 0.1f); - //AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot0, 0, sendFilter0); - - long startTime = 0; - long endTime = 0; - - if (SoundPhysicsCore.Config.performanceLogging) - startTime = System.nanoTime(); - + + /** + * CALLED BY ASM INJECTED CODE! + */ + public static void onPlaySound(final float posX, final float posY, final float posZ, final int sourceID) { evaluateEnvironment(sourceID, posX, posY, posZ); - - if (SoundPhysicsCore.Config.performanceLogging) - { - endTime = System.nanoTime(); - log("Total calculation time for sound " + lastSoundName + ": " + (double)(endTime - startTime)/(double)1000000 + " milliseconds"); - } - - - //System.out.println(soundCategory.getCategoryName()); } - - public static double calculateEntitySoundOffset(Entity entity, SoundEvent sound) - { - if (!sound.getSoundName().getResourcePath().matches(".*step.*")) - { - //log("Offset entity say sound by " + entity.getEyeHeight()); - return entity.getEyeHeight(); - } - else - { - return 0.0; + + /** + * CALLED BY ASM INJECTED CODE! + */ + public static double calculateEntitySoundOffset(final Entity entity, final SoundEvent sound) { + if (stepPattern.matcher(sound.getSoundName().getResourcePath()).matches()) { + return 0; } - //return 0.0; + + return entity.getEyeHeight(); } - - private static float getBlockReflectivity(Int3 blockPos) - { - Block block = mc.theWorld.getBlockState(new BlockPos(blockPos.x, blockPos.y, blockPos.z)).getBlock(); - SoundType soundType = block.getSoundType(); - + + @SuppressWarnings("deprecation") + private static float getBlockReflectivity(final BlockPos blockPos) { + final Block block = mc.world.getBlockState(blockPos).getBlock(); + final SoundType soundType = block.getSoundType(); + float reflectivity = 0.5f; - - if (soundType == SoundType.STONE) - reflectivity = SoundPhysicsCore.Config.stoneReflectivity; - else if (soundType == SoundType.WOOD) - reflectivity = SoundPhysicsCore.Config.woodReflectivity; - else if (soundType == SoundType.GROUND) - reflectivity = SoundPhysicsCore.Config.groundReflectivity; - else if (soundType == SoundType.PLANT) - reflectivity = SoundPhysicsCore.Config.plantReflectivity; - else if (soundType == SoundType.METAL) - reflectivity = SoundPhysicsCore.Config.metalReflectivity; - else if (soundType == SoundType.GLASS) - reflectivity = SoundPhysicsCore.Config.glassReflectivity; - else if (soundType == SoundType.CLOTH) - reflectivity = SoundPhysicsCore.Config.clothReflectivity; - else if (soundType == SoundType.SAND) - reflectivity = SoundPhysicsCore.Config.sandReflectivity; - else if (soundType == SoundType.SNOW) - reflectivity = SoundPhysicsCore.Config.snowReflectivity; - else if (soundType == SoundType.LADDER) - reflectivity = SoundPhysicsCore.Config.woodReflectivity; - else if (soundType == SoundType.ANVIL) - reflectivity = SoundPhysicsCore.Config.metalReflectivity; - - reflectivity *= SoundPhysicsCore.Config.globalBlockReflectance; - + + if (soundType == SoundType.STONE) { + reflectivity = Config.stoneReflectivity; + } else if (soundType == SoundType.WOOD) { + reflectivity = Config.woodReflectivity; + } else if (soundType == SoundType.GROUND) { + reflectivity = Config.groundReflectivity; + } else if (soundType == SoundType.PLANT) { + reflectivity = Config.plantReflectivity; + } else if (soundType == SoundType.METAL) { + reflectivity = Config.metalReflectivity; + } else if (soundType == SoundType.GLASS) { + reflectivity = Config.glassReflectivity; + } else if (soundType == SoundType.CLOTH) { + reflectivity = Config.clothReflectivity; + } else if (soundType == SoundType.SAND) { + reflectivity = Config.sandReflectivity; + } else if (soundType == SoundType.SNOW) { + reflectivity = Config.snowReflectivity; + } else if (soundType == SoundType.LADDER) { + reflectivity = Config.woodReflectivity; + } else if (soundType == SoundType.ANVIL) { + reflectivity = Config.metalReflectivity; + } + + reflectivity *= Config.globalBlockReflectance; + return reflectivity; } - - private static Vec3d getNormalFromFacing(EnumFacing sideHit) - { - /* - Vec3d normal; - if (sideHit == EnumFacing.DOWN) - normal = new Vec3d(0.0, -1.0, 0.0); - else if (sideHit == EnumFacing.UP) - normal = new Vec3d(0.0, 1.0, 0.0); - else if (sideHit == EnumFacing.EAST) - normal = new Vec3d(1.0, 0.0, 0.0); - else if (sideHit == 3) - normal = new Vec3d(-1.0, 0.0, 0.0); - else if (sideHit == 4) - normal = new Vec3d(0.0, 0.0, 1.0); - else - normal = new Vec3d(0.0, 0.0, -1.0); - - return normal; - */ - Vec3d normal; - - Vec3i inormal = sideHit.getDirectionVec(); - - normal = new Vec3d(inormal.getX(), inormal.getY(), inormal.getZ()); - - return normal; + + private static Vec3d getNormalFromFacing(final EnumFacing sideHit) { + return new Vec3d(sideHit.getDirectionVec()); } - - private static Vec3d reflect(Vec3d dir, Vec3d normal) - { - //dir - 2.0 * dot(normal, dir) * normal - double dot = dir.dotProduct(normal); - - double x = dir.xCoord - 2.0 * dot * normal.xCoord; - double y = dir.yCoord - 2.0 * dot * normal.yCoord; - double z = dir.zCoord - 2.0 * dot * normal.zCoord; - + + private static Vec3d reflect(final Vec3d dir, final Vec3d normal) { + final double dot2 = dir.dotProduct(normal) * 2; + + final double x = dir.x - dot2 * normal.x; + final double y = dir.y - dot2 * normal.y; + final double z = dir.z - dot2 * normal.z; + return new Vec3d(x, y, z); } - - private static Vec3d offsetSoundByName(Vec3d soundPos, Vec3d playerPos, String name, String soundCategory) - { + + private static Vec3d offsetSoundByName(final double soundX, final double soundY, final double soundZ, + final Vec3d playerPos, final String name, final SoundCategory category) { double offsetX = 0.0; double offsetY = 0.0; double offsetZ = 0.0; - double offsetTowardsPlayer = 0.0; - - Vec3d toPlayerVector = playerPos.subtract(soundPos).normalize(); - - //names - if (name.matches(".*step.*")) - { + + double tempNormX = 0; + double tempNormY = 0; + double tempNormZ = 0; + + if (soundY % 1.0 < 0.001 || stepPattern.matcher(name).matches()) { offsetY = 0.1; } - - //categories - if (soundCategory.matches("block") || soundCategory.matches("record")) - { - offsetTowardsPlayer = 0.89; - } - - if (soundPos.yCoord % 1.0 < 0.001 && soundPos.yCoord > 0.01) - { - offsetY = 0.1; + + if (category == SoundCategory.BLOCKS || blockPattern.matcher(name).matches()) { + // The ray will probably hit the block that it's emitting from + // before + // escaping. Offset the ray start position towards the player by the + // diagonal half length of a cube + + tempNormX = playerPos.x - soundX; + tempNormY = playerPos.y - soundY; + tempNormZ = playerPos.z - soundZ; + final double length = Math.sqrt(tempNormX * tempNormX + tempNormY * tempNormY + tempNormZ * tempNormZ); + tempNormX /= length; + tempNormY /= length; + tempNormZ /= length; + // 0.867 > square root of 0.5^2 * 3 + offsetTowardsPlayer = 0.867; + offsetX += tempNormX * offsetTowardsPlayer; + offsetY += tempNormY * offsetTowardsPlayer; + offsetZ += tempNormZ * offsetTowardsPlayer; } - - offsetX += toPlayerVector.xCoord * offsetTowardsPlayer; - offsetY += toPlayerVector.yCoord * offsetTowardsPlayer; - offsetZ += toPlayerVector.zCoord * offsetTowardsPlayer; - - //soundPos.xCoord += offsetX; - //soundPos.yCoord += offsetY; - //soundPos.zCoord += offsetZ; - soundPos = soundPos.addVector(offsetX, offsetY, offsetZ); - - //logDetailed("Offset sound by " + offsetX + ", " + offsetY + ", " + offsetZ); - - return soundPos; + + return new Vec3d(soundX + offsetX, soundY + offsetY, soundZ + offsetZ); } - - private static void evaluateEnvironment(int sourceID, float posX, float posY, float posZ) - { - if (posX < 0.01f && posY < 0.01f && posZ < 0.01f) - { - //logDetailed("Menu sound!"); - + + @SuppressWarnings("deprecation") + private static void evaluateEnvironment(final int sourceID, final float posX, final float posY, final float posZ) { + if (mc.player == null | mc.world == null | posY <= 0 | lastSoundCategory == SoundCategory.RECORDS + | lastSoundCategory == SoundCategory.MUSIC) { + // posY <= 0 as a condition has to be there: Ingame + // menu clicks do have a player and world present setEnvironment(sourceID, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); return; } - - - if (mc.thePlayer == null) - return; - - if (mc.theWorld == null) - return; - - if (SoundPhysicsCore.Config.skipRainOcclusionTracing && lastSoundName.matches(".*rain.*")) - { + + final boolean isRain = rainPattern.matcher(lastSoundName).matches(); + + if (Config.skipRainOcclusionTracing && isRain) { setEnvironment(sourceID, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); return; } - - + float directCutoff = 1.0f; - float absorptionCoeff = SoundPhysicsCore.Config.globalBlockAbsorption * 3.0f; - - //Direct sound occlusion - Vec3d soundPos = new Vec3d(posX, posY, posZ); - Vec3d playerPos = mc.thePlayer.getPositionVector(); - playerPos = new Vec3d(playerPos.xCoord, playerPos.yCoord + mc.thePlayer.getEyeHeight(), playerPos.zCoord); - - soundPos = offsetSoundByName(soundPos, playerPos, lastSoundName, lastSoundCategory.getName()); - - float soundDistance = (float)soundPos.distanceTo(playerPos); - - //Vec3d toPlayerVector = soundPos.subtract(playerPos).normalize(); - Vec3d toPlayerVector = playerPos.subtract(soundPos).normalize(); - - logGeneral("Player pos: " + playerPos.xCoord + ", " + playerPos.yCoord + ", " + playerPos.zCoord + " Sound Pos: " + soundPos.xCoord + ", " + soundPos.yCoord + ", " + soundPos.zCoord + " To player vector: " + toPlayerVector.xCoord + ", " + toPlayerVector.yCoord + ", " + toPlayerVector.zCoord); - - //Cast a ray from the source towards the player - //The ray will probably hit the block that it's emitting from before escaping. Offset the ray start position towards the player by the diagonal half length of a cube - Vec3d rayOrigin = new Vec3d(soundPos.xCoord, soundPos.yCoord, soundPos.zCoord); - if (lastSoundName.matches(".*block.*")) - { - rayOrigin = rayOrigin.add(toPlayerVector.scale(0.867)); - } - - - boolean thisHitSolid = false; //TODO: This will be true if the sound doesn't come from inside a block! - boolean firstHit = true; - Vec3d solidEntryPoint = new Vec3d(0.0, 0.0, 0.0); - int numOcclusionHits = 0; - + final float absorptionCoeff = Config.globalBlockAbsorption * 3.0f; + + final Vec3d playerPos = new Vec3d(mc.player.posX, mc.player.posY + mc.player.getEyeHeight(), mc.player.posZ); + final Vec3d soundPos = offsetSoundByName(posX, posY, posZ, playerPos, lastSoundName, lastSoundCategory); + final Vec3d normalToPlayer = playerPos.subtract(soundPos).normalize(); + + Vec3d rayOrigin = soundPos; + float occlusionAccumulation = 0.0f; - - for(int i = 0; i < 10; i++) - { - RayTraceResult rayHit = mc.theWorld.rayTraceBlocks(rayOrigin, playerPos, true); - - //If we hit a block - if (rayHit != null) - { - numOcclusionHits++; - //Get the normal of the side hit - //Vec3d hitNormal = getNormalFromFacing(rayHit.sideHit); - - //int nextBlockPosX = (int)Math.floor(rayHit.hitVec.xCoord + toPlayerVector.xCoord * 0.001); - //int nextBlockPosY = (int)Math.floor(rayHit.hitVec.xCoord + toPlayerVector.xCoord * 0.001); - //int nextBlockPosZ = (int)Math.floor(rayHit.hitVec.xCoord + toPlayerVector.xCoord * 0.001); - - //Block blockHit = mc.theWorld.getBlock(rayHit.blockX, rayHit.blockY, rayHit.blockZ); - Block blockHit = mc.theWorld.getBlockState(rayHit.getBlockPos()).getBlock(); - - float blockOcclusion = 1.0f; - - if (!blockHit.isOpaqueCube(blockHit.getDefaultState())) - { - //log("not a solid block!"); - blockOcclusion *= 0.15f; - } - - logOcclusion(blockHit.getUnlocalizedName() + " " + rayHit.hitVec.xCoord + ", " + rayHit.hitVec.yCoord + ", " + rayHit.hitVec.zCoord); - - //Accumulate density - occlusionAccumulation += blockOcclusion; - //occlusionAccumulation += 1.0f * (1.0f / (float)numOcclusionHits); - - //Set the new ray step pos - //rayOrigin.xCoord = rayHit.hitVec.xCoord + toPlayerVector.xCoord * 0.01; - //rayOrigin.yCoord = rayHit.hitVec.yCoord + toPlayerVector.yCoord * 0.01; - //rayOrigin.zCoord = rayHit.hitVec.zCoord + toPlayerVector.zCoord * 0.01; - //rayOrigin.add(rayHit.hitVec.scale(0.01)); - //rayOrigin = rayHit.hitVec.add(toPlayerVector.scale(0.01)); - rayOrigin = new Vec3d(rayHit.hitVec.xCoord + toPlayerVector.xCoord * 0.1, rayHit.hitVec.yCoord + toPlayerVector.yCoord * 0.1, rayHit.hitVec.zCoord + toPlayerVector.zCoord * 0.1); - //rayOrigin = new Vec3d(rayOrigin.xCoord, rayOrigin.yCoord + 2.0, rayOrigin.zCoord); - - logOcclusion("New trace position: " + rayOrigin.xCoord + ", " + rayOrigin.yCoord + ", " + rayOrigin.zCoord); - - //System.out.println(rayHit.sideHit); - //cutoff = 0.05f; - - thisHitSolid = !thisHitSolid; - firstHit = false; - } - else - { - //System.out.println("Didn't hit anything!"); + + for (int i = 0; i < 10; i++) { + final RayTraceResult rayHit = mc.world.rayTraceBlocks(rayOrigin, playerPos, true); + + if (rayHit == null) { break; } - + + final Block blockHit = mc.world.getBlockState(rayHit.getBlockPos()).getBlock(); + + float blockOcclusion = 1.0f; + + if (!blockHit.isOpaqueCube(blockHit.getDefaultState())) { + // log("not a solid block!"); + blockOcclusion *= 0.15f; + } + + occlusionAccumulation += blockOcclusion; + + rayOrigin = new Vec3d(rayHit.hitVec.x + normalToPlayer.x * 0.1, rayHit.hitVec.y + normalToPlayer.y * 0.1, + rayHit.hitVec.z + normalToPlayer.z * 0.1); } - - directCutoff = (float)Math.exp(-occlusionAccumulation * absorptionCoeff); - float directGain = (float)Math.pow(directCutoff, 0.1); - - logOcclusion("direct cutoff: " + directCutoff + " direct gain:" + directGain); - - //Calculate reverb parameters for this sound + + directCutoff = (float) Math.exp(-occlusionAccumulation * absorptionCoeff); + float directGain = (float) Math.pow(directCutoff, 0.1); + + // Calculate reverb parameters for this sound float sendGain0 = 0.0f; float sendGain1 = 0.0f; float sendGain2 = 0.0f; float sendGain3 = 0.0f; - + float sendCutoff0 = 1.0f; float sendCutoff1 = 1.0f; float sendCutoff2 = 1.0f; float sendCutoff3 = 1.0f; - - - if (mc.thePlayer.isInsideOfMaterial(Material.WATER)) - { - directCutoff *= 1.0f - SoundPhysicsCore.Config.underwaterFilter; + + if (mc.player.isInsideOfMaterial(Material.WATER)) { + directCutoff *= 1.0f - Config.underwaterFilter; } - - - if (lastSoundName.matches(".*rain.*")) - { - setEnvironment(sourceID, sendGain0, sendGain1, sendGain2, sendGain3, sendCutoff0, sendCutoff1, sendCutoff2, sendCutoff3, directCutoff, directGain); + + if (isRain) { + setEnvironment(sourceID, sendGain0, sendGain1, sendGain2, sendGain3, sendCutoff0, sendCutoff1, sendCutoff2, + sendCutoff3, directCutoff, directGain); return; } - - - //Shoot rays around sound + + // Shoot rays around sound final float phi = 1.618033988f; - final float gAngle = phi * (float)Math.PI * 2.0f; + final float gAngle = phi * (float) Math.PI * 2.0f; final float maxDistance = 256.0f; - - final int numRays = SoundPhysicsCore.Config.environmentEvaluationRays; + + final int numRays = Config.environmentEvaluationRays; final int rayBounces = 4; - float reflectionEnergySum = 0.0f; - float rayLengthSum = 0.0f; - int numRaysHit = 0; - - int secondaryRayHits = 0; - float secondaryRayLengthSum = 0.0f; - float secondaryReflectionEnergySum = 0.0f; - - int[] rayHits = new int[rayBounces]; - - float totalReflectivityRatio = 0.0f; - float[] bounceReflectivityRatio = new float[rayBounces]; - + + final float[] bounceReflectivityRatio = new float[rayBounces]; + float sharedAirspace = 0.0f; - - float rcpTotalRays = 1.0f / (numRays * rayBounces); - float rcpPrimaryRays = 1.0f / (numRays); - - final double reflectionEnergyCurve = 1.0; - - for (int i = 0; i < numRays; i++) - { - float fi = (float)i; - float fiN = (float)fi / (float)numRays; - float longitude = gAngle * fi * 1.0f; - float latitude = (float)Math.asin(fiN * 2.0f - 1.0f); - - Vec3d rayDir = new Vec3d(0.0, 0.0, 0.0); - //rayDir.xCoord = Math.cos(latitude) * Math.cos(longitude); - //rayDir.zCoord = Math.cos(latitude) * Math.sin(longitude); - //rayDir.yCoord = Math.sin(latitude); - { - double x = Math.cos(latitude) * Math.cos(longitude); - double y = Math.cos(latitude) * Math.sin(longitude); - double z = Math.sin(latitude); - rayDir = new Vec3d(x, y, z); - } - - - //Vec3d rayStart = Vec3d.createVectorHelper(soundPos.xCoord + rayDir.xCoord * 0.867, soundPos.yCoord + rayDir.yCoord * 0.867, soundPos.zCoord + rayDir.zCoord * 0.867); - Vec3d rayStart = new Vec3d(soundPos.xCoord, soundPos.yCoord, soundPos.zCoord); - - Vec3d rayEnd = new Vec3d(rayStart.xCoord + rayDir.xCoord * maxDistance, rayStart.yCoord + rayDir.yCoord * maxDistance, rayStart.zCoord + rayDir.zCoord * maxDistance); - - RayTraceResult rayHit = mc.theWorld.rayTraceBlocks(rayStart, rayEnd, true); - - if (rayHit != null) - { - double rayLength = soundPos.distanceTo(rayHit.hitVec); - rayLengthSum += (float)rayLength; - reflectionEnergySum += 1.0f / numRays; - numRaysHit++; - - //Additional bounces - Int3 lastHitBlock = Int3.create(rayHit.getBlockPos().getX(), rayHit.getBlockPos().getY(), rayHit.getBlockPos().getZ()); + + final float rcpTotalRays = 1.0f / (numRays * rayBounces); + final float rcpPrimaryRays = 1.0f / numRays; + + for (int i = 0; i < numRays; i++) { + final float fi = i; + final float fiN = fi / numRays; + final float longitude = gAngle * fi; + final float latitude = (float) Math.asin(fiN * 2.0f - 1.0f); + + final Vec3d rayDir = new Vec3d(Math.cos(latitude) * Math.cos(longitude), + Math.cos(latitude) * Math.sin(longitude), Math.sin(latitude)); + + final Vec3d rayStart = new Vec3d(soundPos.x, soundPos.y, soundPos.z); + + final Vec3d rayEnd = new Vec3d(rayStart.x + rayDir.x * maxDistance, rayStart.y + rayDir.y * maxDistance, + rayStart.z + rayDir.z * maxDistance); + + final RayTraceResult rayHit = mc.world.rayTraceBlocks(rayStart, rayEnd, true); + + if (rayHit != null) { + final double rayLength = soundPos.distanceTo(rayHit.hitVec); + + // Additional bounces + BlockPos lastHitBlock = rayHit.getBlockPos(); Vec3d lastHitPos = rayHit.hitVec; Vec3d lastHitNormal = getNormalFromFacing(rayHit.sideHit); Vec3d lastRayDir = rayDir; - - - - float totalRayDistance = (float)rayLength; - - //Secondary ray bounces - for (int j = 0; j < rayBounces; j++) - { - float fj = (float)j / rayBounces; - Vec3d newRayDir = reflect(lastRayDir, lastHitNormal); - //Vec3d newRayDir = lastHitNormal; - Vec3d newRayStart = new Vec3d(lastHitPos.xCoord + lastHitNormal.xCoord * 0.01, lastHitPos.yCoord + lastHitNormal.yCoord * 0.01, lastHitPos.zCoord + lastHitNormal.zCoord * 0.01); - Vec3d newRayEnd = new Vec3d(newRayStart.xCoord + newRayDir.xCoord * maxDistance, newRayStart.yCoord + newRayDir.yCoord * maxDistance, newRayStart.zCoord + newRayDir.zCoord * maxDistance); - - //log("New ray dir: " + newRayDir.xCoord + ", " + newRayDir.yCoord + ", " + newRayDir.zCoord); - - RayTraceResult newRayHit = mc.theWorld.rayTraceBlocks(newRayStart, newRayEnd, true); - - float soundDirToPlayerDot = (float)newRayDir.dotProduct(toPlayerVector); - //float energyTowardsPlayer = (float)Math.pow(MathHelper.clamp_float(soundDirToPlayerDot, 0.0f, 1.0f), 1.0f); + + float totalRayDistance = (float) rayLength; + + // Secondary ray bounces + for (int j = 0; j < rayBounces; j++) { + final Vec3d newRayDir = reflect(lastRayDir, lastHitNormal); + // Vec3d newRayDir = lastHitNormal; + final Vec3d newRayStart = new Vec3d(lastHitPos.x + lastHitNormal.x * 0.01, + lastHitPos.y + lastHitNormal.y * 0.01, lastHitPos.z + lastHitNormal.z * 0.01); + final Vec3d newRayEnd = new Vec3d(newRayStart.x + newRayDir.x * maxDistance, + newRayStart.y + newRayDir.y * maxDistance, newRayStart.z + newRayDir.z * maxDistance); + + final RayTraceResult newRayHit = mc.world.rayTraceBlocks(newRayStart, newRayEnd, true); + float energyTowardsPlayer = 0.25f; - float blockReflectivity = getBlockReflectivity(lastHitBlock); - energyTowardsPlayer *= blockReflectivity * 0.75f + 0.25f; - float bounceToPlayerDistance = (float)lastHitPos.distanceTo(playerPos); - //energyTowardsPlayer *= 1.0f / ((float)Math.pow(bounceToPlayerDistance, 2.0) + 0.01f); - - totalReflectivityRatio += blockReflectivity; - - if (newRayHit != null) - { - //if ray got obstructed before it reached the player, it wasn't heard - if (lastHitPos.distanceTo(newRayHit.hitVec) < bounceToPlayerDistance) - { - //energyTowardsPlayer *= 0.0f; - } - - double newRayLength = lastHitPos.distanceTo(newRayHit.hitVec); - secondaryRayLengthSum += newRayLength; - secondaryReflectionEnergySum = 0.0f; - secondaryRayHits++; - rayHits[j]++; - bounceReflectivityRatio[j] += (float)Math.pow(blockReflectivity, reflectionEnergyCurve); - + final float blockReflectivity = getBlockReflectivity(lastHitBlock); + energyTowardsPlayer *= blockReflectivity * 0.75f + 0.25f; + + if (newRayHit == null) { + totalRayDistance += lastHitPos.distanceTo(playerPos); + } else { + final double newRayLength = lastHitPos.distanceTo(newRayHit.hitVec); + + bounceReflectivityRatio[j] += blockReflectivity; + totalRayDistance += newRayLength; - + lastHitPos = newRayHit.hitVec; lastHitNormal = getNormalFromFacing(newRayHit.sideHit); lastRayDir = newRayDir; - lastHitBlock = Int3.create(newRayHit.getBlockPos().getX(), newRayHit.getBlockPos().getY(), newRayHit.getBlockPos().getZ()); - - - //Cast one final ray towards the player. If it's unobstructed, then the sound source and the player share airspace. - if (SoundPhysicsCore.Config.simplerSharedAirspaceSimulation && j == rayBounces-1 || !SoundPhysicsCore.Config.simplerSharedAirspaceSimulation) - { - Vec3d finalHitToPlayer = playerPos.subtract(lastHitPos).normalize(); - Vec3d finalRayStart = new Vec3d(lastHitPos.xCoord + lastHitNormal.xCoord * 0.01, lastHitPos.yCoord + lastHitNormal.yCoord * 0.01, lastHitPos.zCoord + lastHitNormal.zCoord * 0.01); - - RayTraceResult finalRayHit = mc.theWorld.rayTraceBlocks(finalRayStart, playerPos, true); - - if (finalRayHit == null) - { - //log("Secondary ray hit the player!"); + lastHitBlock = newRayHit.getBlockPos(); + + // Cast one final ray towards the player. If it's + // unobstructed, then the sound source and the player + // share airspace. + if (Config.simplerSharedAirspaceSimulation && j == rayBounces - 1 + || !Config.simplerSharedAirspaceSimulation) { + final Vec3d finalRayStart = new Vec3d(lastHitPos.x + lastHitNormal.x * 0.01, + lastHitPos.y + lastHitNormal.y * 0.01, lastHitPos.z + lastHitNormal.z * 0.01); + + final RayTraceResult finalRayHit = mc.world.rayTraceBlocks(finalRayStart, playerPos, true); + + if (finalRayHit == null) { + // log("Secondary ray hit the player!"); sharedAirspace += 1.0f; } } } - else - { - totalRayDistance += lastHitPos.distanceTo(playerPos); - } - - float reflectionDelay = (float)Math.pow(Math.max(totalRayDistance, 0.0), 1.0) * 0.12f * blockReflectivity; - - float cross0 = 1.0f - MathHelper.clamp_float(Math.abs(reflectionDelay - 0.0f), 0.0f, 1.0f); - float cross1 = 1.0f - MathHelper.clamp_float(Math.abs(reflectionDelay - 1.0f), 0.0f, 1.0f); - float cross2 = 1.0f - MathHelper.clamp_float(Math.abs(reflectionDelay - 2.0f), 0.0f, 1.0f); - //float cross3 = 1.0f - MathHelper.clamp_float(Math.abs(reflectionDelay - 3.0f), 0.0f, 1.0f); - float cross3 = MathHelper.clamp_float(reflectionDelay - 2.0f, 0.0f, 1.0f); - -/* 1.0 / numRays*/ sendGain0 += cross0 * energyTowardsPlayer * 6.4f * rcpTotalRays; + + final float reflectionDelay = (float) Math.max(totalRayDistance, 0.0) * 0.12f * blockReflectivity; + + final float cross0 = 1.0f - MathHelper.clamp(Math.abs(reflectionDelay - 0.0f), 0.0f, 1.0f); + final float cross1 = 1.0f - MathHelper.clamp(Math.abs(reflectionDelay - 1.0f), 0.0f, 1.0f); + final float cross2 = 1.0f - MathHelper.clamp(Math.abs(reflectionDelay - 2.0f), 0.0f, 1.0f); + final float cross3 = MathHelper.clamp(reflectionDelay - 2.0f, 0.0f, 1.0f); + + sendGain0 += cross0 * energyTowardsPlayer * 6.4f * rcpTotalRays; sendGain1 += cross1 * energyTowardsPlayer * 12.8f * rcpTotalRays; sendGain2 += cross2 * energyTowardsPlayer * 12.8f * rcpTotalRays; sendGain3 += cross3 * energyTowardsPlayer * 12.8f * rcpTotalRays; - - //Nowhere to bounce off of, stop bouncing! - if (newRayHit == null) - { + + // Nowhere to bounce off of, stop bouncing! + if (newRayHit == null) { break; } } - - //log("Hit " + mc.theWorld.getBlock(rayHit.blockX, rayHit.blockY, rayHit.blockZ).getUnlocalizedName() + " at " + rayHit.hitVec.xCoord + ", " + rayHit.hitVec.yCoord + ", " + rayHit.hitVec.zCoord + " and travelled " + rayLength + " meters."); - } - else - { - //log("Escaped"); } - + } - - totalReflectivityRatio /= numRays * rayBounces; - - //log("total reflectivity ratio: " + totalReflectivityRatio); - - float rayHitRatio = (float)numRaysHit/(float)numRays; - float avgRayLength = rayLengthSum / (float)numRaysHit; - float avgSecondaryLength = secondaryRayHits != 0 ? secondaryRayLengthSum / secondaryRayHits : 0.0f; - float secondaryHitRatio = (float)secondaryRayHits/(float)(numRays * rayBounces); - - float hitRatioBounce1 = (float)rayHits[0] / (float)numRays; - float hitRatioBounce2 = (float)rayHits[1] / (float)numRays; - float hitRatioBounce3 = (float)rayHits[2] / (float)numRays; - float hitRatioBounce4 = (float)rayHits[3] / (float)numRays; - - bounceReflectivityRatio[0] = (float)Math.pow(bounceReflectivityRatio[0] / (float)numRays, 1.0 / reflectionEnergyCurve); - bounceReflectivityRatio[1] = (float)Math.pow(bounceReflectivityRatio[1] / (float)numRays, 1.0 / reflectionEnergyCurve); - bounceReflectivityRatio[2] = (float)Math.pow(bounceReflectivityRatio[2] / (float)numRays, 1.0 / reflectionEnergyCurve); - bounceReflectivityRatio[3] = (float)Math.pow(bounceReflectivityRatio[3] / (float)numRays, 1.0 / reflectionEnergyCurve); - - + + // log("total reflectivity ratio: " + totalReflectivityRatio); + + bounceReflectivityRatio[0] = bounceReflectivityRatio[0] / numRays; + bounceReflectivityRatio[1] = bounceReflectivityRatio[1] / numRays; + bounceReflectivityRatio[2] = bounceReflectivityRatio[2] / numRays; + bounceReflectivityRatio[3] = bounceReflectivityRatio[3] / numRays; + sharedAirspace *= 64.0f; - - if (SoundPhysicsCore.Config.simplerSharedAirspaceSimulation) + + if (Config.simplerSharedAirspaceSimulation) { sharedAirspace *= rcpPrimaryRays; - else + } else { sharedAirspace *= rcpTotalRays; - - float sharedAirspaceWeight0 = MathHelper.clamp_float(sharedAirspace / 20.0f, 0.0f, 1.0f); - float sharedAirspaceWeight1 = MathHelper.clamp_float(sharedAirspace / 15.0f, 0.0f, 1.0f); - float sharedAirspaceWeight2 = MathHelper.clamp_float(sharedAirspace / 10.0f, 0.0f, 1.0f); - float sharedAirspaceWeight3 = MathHelper.clamp_float(sharedAirspace / 10.0f, 0.0f, 1.0f); - - - sendCutoff0 = (float)Math.exp(-occlusionAccumulation * absorptionCoeff * 1.0f) * (1.0f - sharedAirspaceWeight0) + sharedAirspaceWeight0; - sendCutoff1 = (float)Math.exp(-occlusionAccumulation * absorptionCoeff * 1.0f) * (1.0f - sharedAirspaceWeight1) + sharedAirspaceWeight1; - sendCutoff2 = (float)Math.exp(-occlusionAccumulation * absorptionCoeff * 1.5f) * (1.0f - sharedAirspaceWeight2) + sharedAirspaceWeight2; - sendCutoff3 = (float)Math.exp(-occlusionAccumulation * absorptionCoeff * 1.5f) * (1.0f - sharedAirspaceWeight3) + sharedAirspaceWeight3; - - - //attempt to preserve directionality when airspace is shared by allowing some of the dry signal through but filtered - float averageSharedAirspace = (sharedAirspaceWeight0 + sharedAirspaceWeight1 + sharedAirspaceWeight2 + sharedAirspaceWeight3) * 0.25f; - directCutoff = (float)Math.max((float)Math.pow(averageSharedAirspace, 0.5) * 0.2f, directCutoff); - - directGain = (float)Math.pow(directCutoff, 0.1); - - - - - - //logDetailed("HitRatio0: " + hitRatioBounce1 + " HitRatio1: " + hitRatioBounce2 + " HitRatio2: " + hitRatioBounce3 + " HitRatio3: " + hitRatioBounce4); - - logEnvironment("Bounce reflectivity 0: " + bounceReflectivityRatio[0] + " bounce reflectivity 1: " + bounceReflectivityRatio[1] + " bounce reflectivity 2: " + bounceReflectivityRatio[2] + " bounce reflectivity 3: " + bounceReflectivityRatio[3]); - - - sendGain1 *= (float)Math.pow(bounceReflectivityRatio[1], 1.0); - //sendGain1 += sendGain2 * (1.0f - (float)Math.pow(bounceReflectivityRatio[2], 3.0)) * 0.5f; - //sendGain1 += sendGain3 * (1.0f - (float)Math.pow(bounceReflectivityRatio[3], 4.0)) * 0.5f; - sendGain2 *= (float)Math.pow(bounceReflectivityRatio[2], 3.0); - sendGain3 *= (float)Math.pow(bounceReflectivityRatio[3], 4.0); - - - - - - //good previously - /* - sendGain1 *= (float)Math.pow(hitRatioBounce2, 2.0); - sendGain1 += sendGain2 * (1.0f - (float)Math.pow(hitRatioBounce3, 3.0)) * 0.5f; - sendGain1 += sendGain3 * (1.0f - (float)Math.pow(hitRatioBounce4, 4.0)) * 0.5f; - sendGain2 *= (float)Math.pow(hitRatioBounce3, 3.0); - sendGain3 *= (float)Math.pow(hitRatioBounce4, 4.0); - */ - - sendGain0 = MathHelper.clamp_float(sendGain0 * 1.00f - 0.00f, 0.0f, 1.0f); - sendGain1 = MathHelper.clamp_float(sendGain1 * 1.00f - 0.00f, 0.0f, 1.0f); - sendGain2 = MathHelper.clamp_float(sendGain2 * 1.05f - 0.05f, 0.0f, 1.0f); - sendGain3 = MathHelper.clamp_float(sendGain3 * 1.05f - 0.05f, 0.0f, 1.0f); - - - sendGain0 *= (float)Math.pow(sendCutoff0, 0.1); - sendGain1 *= (float)Math.pow(sendCutoff1, 0.1); - sendGain2 *= (float)Math.pow(sendCutoff2, 0.1); - sendGain3 *= (float)Math.pow(sendCutoff3, 0.1); - - - logEnvironment("Final environment settings: " + sendGain0 + ", " + sendGain1 + ", " + sendGain2 + ", " + sendGain3); - - - //sendGain0 *= sharedAirspaceWeight0 * 0.5f + 0.5f; - //sendGain1 *= sharedAirspaceWeight1 * 0.5f + 0.5f; - //sendGain2 *= sharedAirspaceWeight2 * 0.5f + 0.5f; - //sendGain3 *= sharedAirspaceWeight3 * 0.5f + 0.5f; - - //sendGain0 = 1.0f; - //sendGain1 = 1.0f; - //sendGain2 = 0.0f; - //sendGain3 = 0.0f; - - if (mc.thePlayer.isInWater()) - { + } + + final float sharedAirspaceWeight0 = MathHelper.clamp(sharedAirspace / 20.0f, 0.0f, 1.0f); + final float sharedAirspaceWeight1 = MathHelper.clamp(sharedAirspace / 15.0f, 0.0f, 1.0f); + final float sharedAirspaceWeight2 = MathHelper.clamp(sharedAirspace / 10.0f, 0.0f, 1.0f); + final float sharedAirspaceWeight3 = MathHelper.clamp(sharedAirspace / 10.0f, 0.0f, 1.0f); + + sendCutoff0 = (float) Math.exp(-occlusionAccumulation * absorptionCoeff * 1.0f) * (1.0f - sharedAirspaceWeight0) + + sharedAirspaceWeight0; + sendCutoff1 = (float) Math.exp(-occlusionAccumulation * absorptionCoeff * 1.0f) * (1.0f - sharedAirspaceWeight1) + + sharedAirspaceWeight1; + sendCutoff2 = (float) Math.exp(-occlusionAccumulation * absorptionCoeff * 1.5f) * (1.0f - sharedAirspaceWeight2) + + sharedAirspaceWeight2; + sendCutoff3 = (float) Math.exp(-occlusionAccumulation * absorptionCoeff * 1.5f) * (1.0f - sharedAirspaceWeight3) + + sharedAirspaceWeight3; + + // attempt to preserve directionality when airspace is shared by + // allowing some of the dry signal through but filtered + final float averageSharedAirspace = (sharedAirspaceWeight0 + sharedAirspaceWeight1 + sharedAirspaceWeight2 + + sharedAirspaceWeight3) * 0.25f; + directCutoff = Math.max((float) Math.pow(averageSharedAirspace, 0.5) * 0.2f, directCutoff); + + directGain = (float) Math.pow(directCutoff, 0.1); + + sendGain1 *= bounceReflectivityRatio[1]; + sendGain2 *= (float) Math.pow(bounceReflectivityRatio[2], 3.0); + sendGain3 *= (float) Math.pow(bounceReflectivityRatio[3], 4.0); + + sendGain0 = MathHelper.clamp(sendGain0, 0.0f, 1.0f); + sendGain1 = MathHelper.clamp(sendGain1, 0.0f, 1.0f); + sendGain2 = MathHelper.clamp(sendGain2 * 1.05f - 0.05f, 0.0f, 1.0f); + sendGain3 = MathHelper.clamp(sendGain3 * 1.05f - 0.05f, 0.0f, 1.0f); + + sendGain0 *= (float) Math.pow(sendCutoff0, 0.1); + sendGain1 *= (float) Math.pow(sendCutoff1, 0.1); + sendGain2 *= (float) Math.pow(sendCutoff2, 0.1); + sendGain3 *= (float) Math.pow(sendCutoff3, 0.1); + + if (mc.player.isInWater()) { sendCutoff0 *= 0.4f; sendCutoff1 *= 0.4f; sendCutoff2 *= 0.4f; sendCutoff3 *= 0.4f; } - - /* - //Set reverb send filter values and set source to send to all reverb fx slots - EFX10.alFilterf(sendFilter0, EFX10.AL_LOWPASS_GAIN, sendGain0); - EFX10.alFilterf(sendFilter0, EFX10.AL_LOWPASS_GAINHF, sendCutoff0); - AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot0, 0, sendFilter0); - - EFX10.alFilterf(sendFilter1, EFX10.AL_LOWPASS_GAIN, sendGain1); - EFX10.alFilterf(sendFilter1, EFX10.AL_LOWPASS_GAINHF, sendCutoff1); - AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot1, 1, sendFilter1); - - EFX10.alFilterf(sendFilter2, EFX10.AL_LOWPASS_GAIN, sendGain2); - EFX10.alFilterf(sendFilter2, EFX10.AL_LOWPASS_GAINHF, sendCutoff2); - AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot2, 2, sendFilter2); - - EFX10.alFilterf(sendFilter3, EFX10.AL_LOWPASS_GAIN, sendGain3); - EFX10.alFilterf(sendFilter3, EFX10.AL_LOWPASS_GAINHF, sendCutoff3); - AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot3, 3, sendFilter3); - - EFX10.alFilterf(directFilter0, EFX10.AL_LOWPASS_GAINHF, directCutoff); - AL10.alSourcei(sourceID, EFX10.AL_DIRECT_FILTER, directFilter0); - */ - - - - //sendGain0 = 1.0f; - //sendGain1 = 1.0f; - //sendGain2 = 1.0f; - //sendGain3 = 1.0f; - - - - setEnvironment(sourceID, sendGain0, sendGain1, sendGain2, sendGain3, sendCutoff0, sendCutoff1, sendCutoff2, sendCutoff3, directCutoff, directGain); + + setEnvironment(sourceID, sendGain0, sendGain1, sendGain2, sendGain3, sendCutoff0, sendCutoff1, sendCutoff2, + sendCutoff3, directCutoff, directGain); } - - private static void setEnvironment(int sourceID, float sendGain0, float sendGain1, float sendGain2, float sendGain3, float sendCutoff0, float sendCutoff1, - float sendCutoff2, float sendCutoff3, float directCutoff, float directGain) - { - //Set reverb send filter values and set source to send to all reverb fx slots + + private static void setEnvironment(final int sourceID, final float sendGain0, final float sendGain1, + final float sendGain2, final float sendGain3, final float sendCutoff0, final float sendCutoff1, + final float sendCutoff2, final float sendCutoff3, final float directCutoff, final float directGain) { + // Set reverb send filter values and set source to send to all reverb fx + // slots EFX10.alFilterf(sendFilter0, EFX10.AL_LOWPASS_GAIN, sendGain0); EFX10.alFilterf(sendFilter0, EFX10.AL_LOWPASS_GAINHF, sendCutoff0); - AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot0, 0, sendFilter0); - + AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot0, 0, sendFilter0); + EFX10.alFilterf(sendFilter1, EFX10.AL_LOWPASS_GAIN, sendGain1); EFX10.alFilterf(sendFilter1, EFX10.AL_LOWPASS_GAINHF, sendCutoff1); - AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot1, 1, sendFilter1); - + AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot1, 1, sendFilter1); + EFX10.alFilterf(sendFilter2, EFX10.AL_LOWPASS_GAIN, sendGain2); EFX10.alFilterf(sendFilter2, EFX10.AL_LOWPASS_GAINHF, sendCutoff2); - AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot2, 2, sendFilter2); - + AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot2, 2, sendFilter2); + EFX10.alFilterf(sendFilter3, EFX10.AL_LOWPASS_GAIN, sendGain3); EFX10.alFilterf(sendFilter3, EFX10.AL_LOWPASS_GAINHF, sendCutoff3); - AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot3, 3, sendFilter3); - + AL11.alSource3i(sourceID, EFX10.AL_AUXILIARY_SEND_FILTER, auxFXSlot3, 3, sendFilter3); + EFX10.alFilterf(directFilter0, EFX10.AL_LOWPASS_GAIN, directGain); EFX10.alFilterf(directFilter0, EFX10.AL_LOWPASS_GAINHF, directCutoff); AL10.alSourcei(sourceID, EFX10.AL_DIRECT_FILTER, directFilter0); - - AL10.alSourcef(sourceID, EFX10.AL_AIR_ABSORPTION_FACTOR, SoundPhysicsCore.Config.airAbsorption); - } - - - private static float calculateAttenuation(double x, double y, double z) - { - if (SoundPhysics.mc.thePlayer != null) - { - Vec3d playerPos = SoundPhysics.mc.thePlayer.getPositionVector(); - - double soundDistance = playerPos.distanceTo(new Vec3d(x, y, z)); - - float atten = (float)Math.max(1.0 - soundDistance / 16.0, 0.0f); - - //logDetailed("Sound attenuation: " + atten); - - return atten; - } - else - { - //System.out.println("NULL PLAYER"); - return 1.0f; - } + + AL10.alSourcef(sourceID, EFX10.AL_AIR_ABSORPTION_FACTOR, Config.airAbsorption); } - - + /** - * Applies the parameters in the enum ReverbParams to the main reverb effect. + * Applies the parameters in the enum ReverbParams to the main reverb + * effect. */ - protected static void setReverbParams(ReverbParams r, int auxFXSlot, int reverbSlot) - { - /* - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_DECAY_TIME, r.decayTime); //Set default parameters - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_DENSITY, r.density); - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_DIFFUSION, r.diffusion); - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_GAIN, r.gain); - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_GAINHF, r.gainHF); - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_DECAY_HFRATIO, r.decayHFRatio); - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_REFLECTIONS_GAIN, r.reflectionsGain); - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_REFLECTIONS_DELAY, r.reflectionsDelay); - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_LATE_REVERB_GAIN, r.lateReverbGain); - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_LATE_REVERB_DELAY, r.lateReverbDelay); - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_AIR_ABSORPTION_GAINHF, r.airAbsorptionGainHF); - EFX10.alEffectf(reverbSlot, EFX10.AL_REVERB_ROOM_ROLLOFF_FACTOR, r.roomRolloffFactor); - EFX10.alEffecti(reverbSlot, EFX10.AL_REVERB_DECAY_HFLIMIT, AL10.AL_TRUE); - */ - - EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_DENSITY, r.density); //Set default parameters + protected static void setReverbParams(final ReverbParams r, final int auxFXSlot, final int reverbSlot) { + EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_DENSITY, r.density); checkErrorLog("Error while assigning reverb density: " + r.density); - EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_DIFFUSION, r.diffusion); //Set default parameters + + EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_DIFFUSION, r.diffusion); checkErrorLog("Error while assigning reverb diffusion: " + r.diffusion); - EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_GAIN, r.gain); //Set default parameters + + EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_GAIN, r.gain); checkErrorLog("Error while assigning reverb gain: " + r.gain); - EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_GAINHF, r.gainHF); //Set default parameters + + EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_GAINHF, r.gainHF); checkErrorLog("Error while assigning reverb gainHF: " + r.gainHF); - EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_DECAY_TIME, r.decayTime); //Set default parameters + + EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_DECAY_TIME, r.decayTime); checkErrorLog("Error while assigning reverb decayTime: " + r.decayTime); - EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_DECAY_HFRATIO, r.decayHFRatio); //Set default parameters + + EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_DECAY_HFRATIO, r.decayHFRatio); checkErrorLog("Error while assigning reverb decayHFRatio: " + r.decayHFRatio); - EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_REFLECTIONS_GAIN, r.reflectionsGain); //Set default parameters + + EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_REFLECTIONS_GAIN, r.reflectionsGain); checkErrorLog("Error while assigning reverb reflectionsGain: " + r.reflectionsGain); - EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_LATE_REVERB_GAIN, r.lateReverbGain); //Set default parameters + + EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_LATE_REVERB_GAIN, r.lateReverbGain); checkErrorLog("Error while assigning reverb lateReverbGain: " + r.lateReverbGain); - EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_LATE_REVERB_DELAY, r.lateReverbDelay); //Set default parameters + + EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_LATE_REVERB_DELAY, r.lateReverbDelay); checkErrorLog("Error while assigning reverb lateReverbDelay: " + r.lateReverbDelay); - EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_AIR_ABSORPTION_GAINHF, r.airAbsorptionGainHF); //Set default parameters + + EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_AIR_ABSORPTION_GAINHF, r.airAbsorptionGainHF); checkErrorLog("Error while assigning reverb airAbsorptionGainHF: " + r.airAbsorptionGainHF); - EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, r.roomRolloffFactor); //Set default parameters + + EFX10.alEffectf(reverbSlot, EFX10.AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, r.roomRolloffFactor); checkErrorLog("Error while assigning reverb roomRolloffFactor: " + r.roomRolloffFactor); - - - //Attach updated effect object + + // Attach updated effect object EFX10.alAuxiliaryEffectSloti(auxFXSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbSlot); } - - protected static void log(String message) - { - System.out.println(logPrefix + ": " + message); - } - - protected static void logOcclusion(String message) - { - if (!SoundPhysicsCore.Config.occlusionLogging) - return; - - System.out.println(logPrefix + " [OCCLUSION] " + ": " + message); - } - - protected static void logEnvironment(String message) - { - if (!SoundPhysicsCore.Config.environmentLogging) - return; - - System.out.println(logPrefix + " [ENVIRONMENT] " + ": " + message); - } - - - protected static void logGeneral(String message) - { - if (!SoundPhysicsCore.Config.debugLogging) - return; - - System.out.println(logPrefix + ": " + message); + + public static void log(final String message) { + System.out.println(logPrefix.concat(" : ").concat(message)); } - - - protected static void logError(String errorMessage) - { - System.out.println(logPrefix + " [ERROR]: " + errorMessage); + + public static void logError(final String errorMessage) { + System.out.println(logPrefix.concat(" [ERROR]: ").concat(errorMessage)); } - - protected static boolean checkErrorLog(String errorMessage) - { - int error = AL10.alGetError(); - String errorName; - - if (error != 0) - { - switch(error) - { - case AL10.AL_INVALID_NAME: errorName = "AL_INVALID_NAME"; break; - case AL10.AL_INVALID_ENUM: errorName = "AL_INVALID_ENUM"; break; - case AL10.AL_INVALID_VALUE: errorName = "AL_INVALID_VALUE"; break; - case AL10.AL_INVALID_OPERATION: errorName = "AL_INVALID_OPERATION"; break; - case AL10.AL_OUT_OF_MEMORY: errorName = "AL_OUT_OF_MEMORY"; break; - default: errorName = Integer.toString(error); break; - } - - System.out.println(logPrefix + " [ERROR]: " + errorMessage + " OpenAL error " + errorName); - return true; - } - else - { + + protected static boolean checkErrorLog(final String errorMessage) { + final int error = AL10.alGetError(); + if (error == AL10.AL_NO_ERROR) { return false; } - } - - //TODO: Find fancy way of determining if a sound is going to be sufficiently quiet to not play it. - public static boolean shouldSoundPacketBeSent(double posX, double posY, double posZ, double volume) - { - if (mc.thePlayer != null) - { - double distance = getDistanceFromPlayer(posX, posY, posZ); - return distance < 32.0; + + String errorName; + + switch (error) { + case AL10.AL_INVALID_NAME: + errorName = "AL_INVALID_NAME"; + break; + case AL10.AL_INVALID_ENUM: + errorName = "AL_INVALID_ENUM"; + break; + case AL10.AL_INVALID_VALUE: + errorName = "AL_INVALID_VALUE"; + break; + case AL10.AL_INVALID_OPERATION: + errorName = "AL_INVALID_OPERATION"; + break; + case AL10.AL_OUT_OF_MEMORY: + errorName = "AL_OUT_OF_MEMORY"; + break; + default: + errorName = Integer.toString(error); + break; } - else return false; - } - - private static double getDistanceFromPlayer(double posX, double posY, double posZ) - { - double x = mc.thePlayer.posX - posX; - double y = mc.thePlayer.posY - posY; - double z = mc.thePlayer.posZ - posZ; - - x *= x; - y *= y; - z *= z; - - return Math.sqrt(x + y + z); + + logError(errorMessage + " OpenAL error " + errorName); + return true; } + } diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java deleted file mode 100644 index af708867..00000000 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java +++ /dev/null @@ -1,580 +0,0 @@ -package com.sonicether.soundphysics; - -import java.util.Iterator; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.InsnNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.tree.VarInsnNode; - -//import cpw.mods.fml.client.event.ConfigChangedEvent; -//import cpw.mods.fml.common.FMLCommonHandler; -//import cpw.mods.fml.common.Mod; -//import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; -//import cpw.mods.fml.common.event.FMLInitializationEvent; -//import cpw.mods.fml.common.event.FMLPreInitializationEvent; -//import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import net.minecraft.launchwrapper.IClassTransformer; -import net.minecraftforge.common.config.Configuration; -import net.minecraftforge.fml.client.event.ConfigChangedEvent; -import net.minecraftforge.fml.common.FMLCommonHandler; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.event.FMLInitializationEvent; -import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; - -@Mod(modid = SoundPhysicsCore.modid, version = SoundPhysicsCore.version, guiFactory = "com.sonicether.soundphysics.SPGUIFactory") -public class SoundPhysicsCore implements IClassTransformer -{ - public static Configuration configFile; - - @Mod.Instance("soundphysics") - public static SoundPhysicsCore instance; - - public static final String modid = "soundphysics"; - public static final String version = "1.0.0"; - - - //Config variables - public static class Config - { - //general - public static float rolloffFactor = 1.0f; - public static float globalReverbGain = 1.0f; - public static float globalReverbBrightness = 1.0f; - public static double soundDistanceAllowance = 4.0f; - public static float globalBlockAbsorption = 1.0f; - public static float globalBlockReflectance = 1.0f; - public static float airAbsorption = 1.0f; - public static float underwaterFilter = 0.8f; - - //performance - public static boolean skipRainOcclusionTracing = true; - public static int environmentEvaluationRays = 32; - public static boolean simplerSharedAirspaceSimulation = false; - - //block properties - public static float stoneReflectivity = 1.0f; - public static float woodReflectivity = 0.4f; - public static float groundReflectivity = 0.3f; - public static float plantReflectivity = 0.5f; - public static float metalReflectivity = 1.0f; - public static float glassReflectivity = 0.5f; - public static float clothReflectivity = 0.05f; - public static float sandReflectivity = 0.2f; - public static float snowReflectivity = 0.2f; - - //misc - public static boolean debugLogging = false; - public static boolean occlusionLogging = false; - public static boolean environmentLogging = false; - public static boolean performanceLogging = false; - - public static final String categoryGeneral = "general"; - public static final String categoryPerformance = "performance"; - public static final String categoryMaterialProperties = "material properties"; - public static final String categoryMisc = "misc"; - } - - - - - @Mod.EventHandler - public void preInit(FMLPreInitializationEvent event) - { - configFile = new Configuration(event.getSuggestedConfigurationFile()); - syncConfig(); - } - - @Mod.EventHandler - public void init(FMLInitializationEvent event) - { - FMLCommonHandler.instance().bus().register(instance); - } - - @SubscribeEvent - public void onConfigChanged(ConfigChangedEvent.OnConfigChangedEvent eventArgs) - { - if (eventArgs.getModID().equals(modid)) - syncConfig(); - } - - - public static void syncConfig() - { - //General - Config.rolloffFactor = configFile.getFloat("Attenuation Factor", Configuration.CATEGORY_GENERAL, 1.0f, 0.2f, 1.0f, "Affects how quiet a sound gets based on distance. Lower values mean distant sounds are louder. 1.0 is the physically correct value."); - Config.globalReverbGain = configFile.getFloat("Global Reverb Gain", Configuration.CATEGORY_GENERAL, 1.0f, 0.1f, 2.0f, "The global volume of simulated reverberations."); - Config.globalReverbBrightness = configFile.getFloat("Global Reverb Brightness", Configuration.CATEGORY_GENERAL, 1.0f, 0.1f, 2.0f, "The brightness of reverberation. Higher values result in more high frequencies in reverberation. Lower values give a more muffled sound to the reverb."); - Config.globalBlockAbsorption = configFile.getFloat("Global Block Absorption", Configuration.CATEGORY_GENERAL, 1.0f, 0.1f, 4.0f, "The global amount of sound that will be absorbed when traveling through blocks."); - Config.globalBlockReflectance = configFile.getFloat("Global Block Reflectance", Configuration.CATEGORY_GENERAL, 1.0f, 0.1f, 4.0f, "The global amount of sound reflectance energy of all blocks. Lower values result in more conservative reverb simulation with shorter reverb tails. Higher values result in more generous reverb simulation with higher reverb tails."); - Config.soundDistanceAllowance = configFile.getFloat("Sound Distance Allowance", Configuration.CATEGORY_GENERAL, 4.0f, 1.0f, 6.0f, "Minecraft won't allow sounds to play past a certain distance. This parameter is a multiplier for how far away a sound source is allowed to be in order for it to actually play. Values too high can cause polyphony issues."); - Config.airAbsorption = configFile.getFloat("Air Absorption", Configuration.CATEGORY_GENERAL, 1.0f, 0.0f, 5.0f, "A value controlling the amount that air absorbs high frequencies with distance. A value of 1.0 is physically correct for air with normal humidity and temperature. Higher values mean air will absorb more high frequencies with distance. 0 disables this effect."); - Config.underwaterFilter = configFile.getFloat("Underwater Filter", Configuration.CATEGORY_GENERAL, 0.8f, 0.0f, 1.0f, "How much sound is filtered when the player is underwater. 0.0 means no filter. 1.0 means fully filtered."); - - //performance - Config.skipRainOcclusionTracing = configFile.getBoolean("Skip Rain Occlusion Tracing", Config.categoryPerformance, true, "If true, rain sound sources won't trace for sound occlusion. This can help performance during rain."); - Config.environmentEvaluationRays = configFile.getInt("Environment Evaluation Rays", Config.categoryPerformance, 32, 8, 64, "The number of rays to trace to determine reverberation for each sound source. More rays provides more consistent tracing results but takes more time to calculate. Decrease this value if you experience lag spikes when sounds play." ); - Config.simplerSharedAirspaceSimulation = configFile.getBoolean("Simpler Shared Airspace Simulation", Config.categoryPerformance, false, "If true, enables a simpler technique for determining when the player and a sound source share airspace. Might sometimes miss recognizing shared airspace, but it's faster to calculate."); - - //material properties - Config.stoneReflectivity = configFile.getFloat("Stone Reflectivity", Config.categoryMaterialProperties, 1.0f, 0.0f, 1.0f, "Sound reflectivity for stone blocks."); - Config.woodReflectivity = configFile.getFloat("Wood Reflectivity", Config.categoryMaterialProperties, 0.4f, 0.0f, 1.0f, "Sound reflectivity for wooden blocks."); - Config.groundReflectivity = configFile.getFloat("Ground Reflectivity", Config.categoryMaterialProperties, 0.3f, 0.0f, 1.0f, "Sound reflectivity for ground blocks (dirt, gravel, etc)."); - Config.plantReflectivity = configFile.getFloat("Foliage Reflectivity", Config.categoryMaterialProperties, 0.5f, 0.0f, 1.0f, "Sound reflectivity for foliage blocks (leaves, grass, etc.)."); - Config.metalReflectivity = configFile.getFloat("Metal Reflectivity", Config.categoryMaterialProperties, 1.0f, 0.0f, 1.0f, "Sound reflectivity for metal blocks."); - Config.glassReflectivity = configFile.getFloat("Glass Reflectivity", Config.categoryMaterialProperties, 0.5f, 0.0f, 1.0f, "Sound reflectivity for glass blocks."); - Config.clothReflectivity = configFile.getFloat("Cloth Reflectivity", Config.categoryMaterialProperties, 0.05f, 0.0f, 1.0f, "Sound reflectivity for cloth blocks (carpet, wool, etc)."); - Config.sandReflectivity = configFile.getFloat("Sand Reflectivity", Config.categoryMaterialProperties, 0.2f, 0.0f, 1.0f, "Sound reflectivity for sand blocks."); - Config.snowReflectivity = configFile.getFloat("Snow Reflectivity", Config.categoryMaterialProperties, 0.2f, 0.0f, 1.0f, "Sound reflectivity for snow blocks."); - - //misc - Config.debugLogging = configFile.getBoolean("Debug Logging", Config.categoryMisc, false, "General debug logging"); - Config.occlusionLogging = configFile.getBoolean("Occlusion Logging", Config.categoryMisc, false, "Occlusion tracing information logging"); - Config.environmentLogging = configFile.getBoolean("Environment Logging", Config.categoryMisc, false, "Environment evaluation information logging"); - Config.performanceLogging = configFile.getBoolean("Performance Logging", Config.categoryMisc, false, "Performance information logging"); - - if(configFile.hasChanged()) - { - configFile.save(); - SoundPhysics.applyConfigChanges(); - } - } - - - - private void log(String message) - { - if (!Config.debugLogging) - return; - - System.out.println(message); - } - - //arg0: class name, arg1: new name of the class, arg2: chuck of bytecode that's about to be loaded into JVM - @Override public byte[] transform(String arg0, String arg1, byte[] arg2) - { - //System.out.println("TRANSFORM"); - - - - - - //Patch SoundManager - - //SoundPhysics.init() in SoundManager.SoundSystemStarterThread - { - InsnList toInject = new InsnList(); - toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "init", "()V")); - - arg2 = patchMethodInClass(arg0, arg2, - new String[]{"net.minecraft.client.audio.SoundManager$SoundSystemStarterThread", "ccn$a"}, //Target Class name - new String[]{"", ""}, //Target method name - new String[]{"(Lnet/minecraft/client/audio/SoundManager;)V", "(Lccn;)V"}, //Target method signature - Opcodes.INVOKESPECIAL, //Target opcode - AbstractInsnNode.METHOD_INSN, //Target node type - new String[]{"", ""}, //Target node method invocation name - null, - new InsnList[]{toInject, toInject}, //Instructions to inject - false, //Insert before the target node? - 0, - 0, - false, - 0 - ); - } - - //setLastSoundCategory(var6) and setLastSoundName() in SoundManager.playSound() - { - InsnList toInject = new InsnList(); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 7)); - toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundCategory", "(Lnet/minecraft/util/SoundCategory;)V")); - - InsnList toInjectObf = new InsnList(); - toInjectObf.add(new VarInsnNode(Opcodes.ALOAD, 7)); - toInjectObf.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundCategory", "(Lno;)V")); - - - arg2 = patchMethodInClass(arg0, arg2, - new String[]{"net.minecraft.client.audio.SoundManager", "ccn"}, //Target Class name - new String[]{"playSound", "c"}, //Target method name - new String[]{"(Lnet/minecraft/client/audio/ISound;)V", "(Lcbz;)V"}, //Target method signature - Opcodes.INVOKEVIRTUAL, //Target opcode - AbstractInsnNode.METHOD_INSN, //Target node type - new String[]{"setVolume", "setVolume"}, //Target node method invocation name - null, - new InsnList[]{toInject, toInjectObf}, //Instructions to inject - false, //Insert before the target node? - 0, - 0, - false, - 0 - ); - } - - //setLastSoundName(name) in SoundManager.playSound() - { - InsnList toInject = new InsnList(); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 1)); - toInject.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "net/minecraft/client/audio/ISound", "getSoundLocation", "()Lnet/minecraft/util/ResourceLocation;")); - toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "net/minecraft/util/ResourceLocation", "toString", "()Ljava/lang/String;")); - toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", "(Ljava/lang/String;)V")); - - InsnList toInjectObf = new InsnList(); - toInjectObf.add(new VarInsnNode(Opcodes.ALOAD, 1)); - toInjectObf.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "cbz", "a", "()Lkq;")); - toInjectObf.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "kq", "toString", "()Ljava/lang/String;")); - toInjectObf.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", "(Ljava/lang/String;)V")); - - arg2 = patchMethodInClass(arg0, arg2, - new String[]{"net.minecraft.client.audio.SoundManager", "ccn"}, //Target Class name - new String[]{"playSound", "c"}, //Target method name - new String[]{"(Lnet/minecraft/client/audio/ISound;)V", "(Lcbz;)V"}, //Target method signature - Opcodes.INVOKEVIRTUAL, //Target opcode - AbstractInsnNode.METHOD_INSN, //Target node type - new String[]{"setVolume", "setVolume"}, //Target node method invocation name - null, - new InsnList[]{toInject, toInjectObf}, //Instructions to inject - false, //Insert before the target node? - 0, - 0, - false, - 0 - ); - } - - - - //Global volume multiplier - { - InsnList toInject = new InsnList(); - toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", "globalVolumeMultiplier", "F")); - toInject.add(new InsnNode(Opcodes.FMUL)); - - arg2 = patchMethodInClass(arg0, arg2, - new String[]{"net.minecraft.client.audio.SoundManager", "ccn"}, //Target Class name - new String[]{"playSound", "c"}, //Target method name - new String[]{"(Lnet/minecraft/client/audio/ISound;)V", "(Lcbz;)V"}, //Target method signature - Opcodes.INVOKESPECIAL, //Target opcode - AbstractInsnNode.METHOD_INSN, //Target node type - new String[]{"getClampedVolume", "e"}, //Target node method invocation name - new String[]{"(Lnet/minecraft/client/audio/ISound;)F", "(Lcbz;)F"}, //Target node method invocation signature - new InsnList[]{toInject}, //Instructions to inject - false, //Insert before the target node? - 0, //Nodes to delete before the target node (done before injection) - 0, //Nodes to delete after the target node (done before injection) - false, - 0 - ); - } - - - - //onPlaySound(var6) in paulscode.libraries.SourceLWJGLOpenAL.play() - { - InsnList toInject = new InsnList(); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); - toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", "Lpaulscode/sound/Vector3D;")); - toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/Vector3D", "x", "F")); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); - toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", "Lpaulscode/sound/Vector3D;")); - toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/Vector3D", "y", "F")); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); - toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", "Lpaulscode/sound/Vector3D;")); - toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/Vector3D", "z", "F")); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); - toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/SourceLWJGLOpenAL", "channelOpenAL", "Lpaulscode/sound/libraries/ChannelLWJGLOpenAL;")); - toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/ChannelLWJGLOpenAL", "ALSource", "Ljava/nio/IntBuffer;")); - toInject.add(new InsnNode(Opcodes.ICONST_0)); - toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/nio/IntBuffer", "get", "(I)I", false)); - toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "onPlaySound", "(FFFI)V", false)); - - arg2 = patchMethodInClass(arg0, arg2, - new String[]{"paulscode.sound.libraries.SourceLWJGLOpenAL"}, //Target Class name - new String[]{"play"}, //Target method name - new String[]{"(Lpaulscode/sound/Channel;)V"}, //Target method signature - Opcodes.INVOKEVIRTUAL, //Target opcode - AbstractInsnNode.METHOD_INSN, //Target node type - new String[]{"play"}, //Target node method invocation name - null, - new InsnList[]{toInject}, //Instructions to inject - false, //Insert before the target node? - 0, //Nodes to delete before the target node (done before injection) - 0, //Nodes to delete after the target node (done before injection) - false, - 0 - ); - } - - - - //attenuation model and rolloff factor - { - InsnList toInject = new InsnList(); - toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", "attenuationModel", "I")); - toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", "globalRolloffFactor", "F")); - - arg2 = patchMethodInClass(arg0, arg2, - new String[]{"paulscode.sound.SoundSystem"}, //Target Class name - new String[]{"newSource"}, //Target method name - new String[]{"(ZLjava/lang/String;Ljava/net/URL;Ljava/lang/String;ZFFFIF)V"}, //Target method signature - Opcodes.INVOKESPECIAL, //Target opcode - AbstractInsnNode.METHOD_INSN, //Target node type - new String[]{""}, //Target node method invocation name - null, - new InsnList[]{toInject}, //Instructions to inject - true, //Insert before the target node? - 2, //Nodes to delete before the target node (done before injection) - 0, //Nodes to delete after the target node (done before injection) - false, - 0 - ); - } - - - - //Multiply sound distance volume play decision by SoundPhysics.soundDistanceAllowance - { - InsnList toInject = new InsnList(); - toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", "soundDistanceAllowance", "D")); - toInject.add(new InsnNode(Opcodes.DMUL)); - - arg2 = patchMethodInClass(arg0, arg2, - new String[]{"net.minecraft.server.management.PlayerList", "mt"}, //Target Class name - new String[]{"sendToAllNearExcept", "a"}, //Target method name - new String[]{"(Lnet/minecraft/entity/player/EntityPlayer;DDDDILnet/minecraft/network/Packet;)V", "(Laax;DDDDILfm;)V"}, //Target method signature - Opcodes.DCMPG, //Target opcode - AbstractInsnNode.INSN, //Target node type - new String[]{"", ""}, //Target node method invocation name - new String[]{"", ""}, //Target node method invocation signature - new InsnList[]{toInject}, //Instructions to inject - true, //Insert before the target node? - 0, //Nodes to delete before the target node (done before injection) - 0, //Nodes to delete after the target node (done before injection) - false, //Remove the target node? - 0 - ); - } - - - - //Offset entity sound by their eye height - { - InsnList toInject = new InsnList(); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 1)); - toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "calculateEntitySoundOffset", "(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/SoundEvent;)D", false)); - toInject.add(new InsnNode(Opcodes.DADD)); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); - - InsnList toInjectObf = new InsnList(); - toInjectObf.add(new VarInsnNode(Opcodes.ALOAD, 1)); - toInjectObf.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "calculateEntitySoundOffset", "(Lsm;Lnm;)D", false)); - toInjectObf.add(new InsnNode(Opcodes.DADD)); - toInjectObf.add(new VarInsnNode(Opcodes.ALOAD, 0)); - - arg2 = patchMethodInClass(arg0, arg2, - new String[]{"net.minecraft.entity.Entity", "sm"}, //Target Class name - new String[]{"playSound", "a"}, //Target method name - new String[]{"(Lnet/minecraft/util/SoundEvent;FF)V", "(Lnm;FF)V"}, //Target method signature - Opcodes.INVOKEVIRTUAL, //Target opcode - AbstractInsnNode.METHOD_INSN, //Target node type - new String[]{"getSoundCategory", "bC"}, //Target node method invocation name - null, //Target node method invocation signature - new InsnList[]{toInject, toInjectObf}, //Instructions to inject - true, //Insert before the target node? - 0, //Nodes to delete before the target node (done before injection) - 0, //Nodes to delete after the target node (done before injection) - false, //Remove the target node? - -3 //target node offset (injection target node offset) - ); - } - - - return arg2; - } - - /** - * - * @param currentClassName - * @param bytes - * @param targetClassNames {deobfuscatedName, obfuscatedName} - * @param targetMethodNames {deobfuscatedName, obfuscatedName} - * @param targetMethodSignature - * @param targetNodeOpcode - * @param targetNodeType - * @param targetInvocationMethodNames {deobfuscatedName, obfuscatedName} - * @param instructionsToInject - * @param insertBefore - * @return - */ - private byte[] patchMethodInClass(String currentClassName, byte[] bytes, String[] targetClassNames, String[] targetMethodNames, String[] targetMethodSignatures, - int targetNodeOpcode, int targetNodeType, String[] targetInvocationMethodNames, String[] targetInvocationMethodSignatures, InsnList[] instructionsToInjects, - boolean insertBefore, int nodesToDeleteBefore, int nodesToDeleteAfter, boolean deleteTargetNode, int targetNodeOffset) - { - String targetClassName = targetClassNames[0]; - String targetMethodName = targetMethodNames[0]; - String targetInvocationMethodName = targetInvocationMethodNames[0]; - - String targetMethodSignature = targetMethodSignatures[0]; - InsnList instructionsToInject = instructionsToInjects[0]; - boolean obfuscated = false; - - if (targetClassNames.length == 2) - { - if (currentClassName.equals(targetClassNames[1])) - { - targetClassName = targetClassNames.length == 2 ? targetClassNames[1] : targetClassNames[0]; - targetMethodName = targetMethodNames.length == 2 ? targetMethodNames[1] : targetClassNames[0]; - targetInvocationMethodName = targetInvocationMethodNames.length == 2 ? targetInvocationMethodNames[1] : targetInvocationMethodNames[0]; - targetMethodSignature = targetMethodSignatures.length == 2 ? targetMethodSignatures[1] : targetMethodSignatures[0]; - instructionsToInject = instructionsToInjects.length == 2 ? instructionsToInjects[1] : instructionsToInjects[0]; - obfuscated = true; - } - } - - String targetInvocationMethodSignature = null; - if (targetInvocationMethodSignatures != null) - { - targetInvocationMethodSignature = targetInvocationMethodSignatures[0]; - if (obfuscated) - { - targetInvocationMethodSignature = targetInvocationMethodSignatures.length == 2 ? targetInvocationMethodSignatures[1] : targetInvocationMethodSignatures[0]; - } - } - - - //If this isn't the target class, leave! - if (!currentClassName.equals(targetClassName)) - return bytes; - - log("################################################################# Patching Class: " + targetClassName); - - //Setup ASM class manipulation stuff - ClassNode classNode = new ClassNode(); - ClassReader classReader = new ClassReader(bytes); - classReader.accept(classNode, 0); - - - //Now we loop over all of the methods declared inside the class until we get to the target method name - @SuppressWarnings("unchecked") - Iterator methods = classNode.methods.iterator(); - while(methods.hasNext()) - { - MethodNode m = methods.next(); - log("********* Method Name: " + m.name + " Desc: " + m.desc); - int targetIndex = -1; - - //Check if this is the method name and the signature matches - if (m.name.equals(targetMethodName) && m.desc.equals(targetMethodSignature)) - { - log("*************************************** Inside target method: " + targetMethodName); - - AbstractInsnNode currentNode = null; - AbstractInsnNode targetNode = null; - - @SuppressWarnings("unchecked") - Iterator iter = m.instructions.iterator(); - - int index = -1; - - //Loop over the instruction set - while (iter.hasNext()) - { - index++; - currentNode = iter.next(); - - if (currentNode.getOpcode() == targetNodeOpcode) - { - if (targetNodeType == AbstractInsnNode.METHOD_INSN) //If we're looking for a method opcode - { - if (currentNode.getType() == AbstractInsnNode.METHOD_INSN) - { - MethodInsnNode method = (MethodInsnNode)currentNode; - //log("Method found: " + method.name); - if (method.name.equals(targetInvocationMethodName)) - { - if (method.desc.equals(targetInvocationMethodSignature) || targetInvocationMethodSignature == null) - { - log("Found target method invocation for injection: " + targetInvocationMethodName); - targetNode = currentNode; - targetIndex = index; - } - - } - } - } - else - { - if (currentNode.getType() == targetNodeType) - { - log("Found target node for injection: " + targetNodeOpcode); - targetNode = currentNode; - targetIndex = index; - } - } - - } - } - - //Offset the target node by the supplied offset value - if (targetNodeOffset > 0) - { - for (int i = 0; i < targetNodeOffset; i++) - { - targetNode = targetNode.getNext(); - } - } - else if (targetNodeOffset < 0) - { - for (int i = 0; i < -targetNodeOffset; i++) - { - targetNode = targetNode.getPrevious(); - } - } - - if (targetNode != null) //If we've found the target, inject the instructions! - { - for (int i = 0; i < nodesToDeleteBefore; i++) - { - AbstractInsnNode previousNode = targetNode.getPrevious(); - log("Removing Node " + previousNode.getOpcode()); - m.instructions.remove(previousNode); - } - - for (int i = 0; i < nodesToDeleteAfter; i++) - { - AbstractInsnNode nextNode = targetNode.getNext(); - log("Removing Node " + nextNode.getOpcode()); - m.instructions.remove(nextNode); - } - - - - if (insertBefore) - m.instructions.insertBefore(targetNode, instructionsToInject); - else - m.instructions.insert(targetNode, instructionsToInject); - - if (deleteTargetNode) - { - m.instructions.remove(targetNode); - } - - log("Patching complete!----------------------------------------------------------------------------------------"); - } - break; - } - } - - ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); - classNode.accept(writer); - return writer.toByteArray(); - } -} diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index a06df53c..8241d747 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -3,14 +3,9 @@ "modid": "soundphysics", "name": "Sound Physics", "description": "Provides realistic sound attenuation, reverberation, and absorption through blocks.", - "version": "1.0.0", - "mcversion": "1.11", + "version": "1.0.4", + "mcversion": "1.12.2", "url": "", - "updateUrl": "", - "authorList": ["Sonic Ether"], - //"credits": "", - "logoFile": "", - "screenshots": [], - "dependencies": [] + "authorList": ["Sonic Ether","daipenger"] } ] diff --git a/z_Link.bat b/z_Link.bat new file mode 100644 index 00000000..a1a90a1d --- /dev/null +++ b/z_Link.bat @@ -0,0 +1 @@ +gradlew eclipse \ No newline at end of file diff --git a/z_Setup.bat b/z_Setup.bat new file mode 100644 index 00000000..57a83e41 --- /dev/null +++ b/z_Setup.bat @@ -0,0 +1 @@ +gradlew setupDecompWorkspace \ No newline at end of file