From 232a6507bf0099a3525ab97c8018ad6dfc54c018 Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 5 Apr 2017 22:34:12 +0200 Subject: [PATCH 01/39] Put in all my build specific stuff --- .gitattributes | 17 +++++++++++ .gitignore | 25 +++++++++++++++ BUILD.bat | 3 ++ build.gradle | 77 +++++++++++++++++++++++++++++++++++++++++++++++ gradle.properties | 3 ++ z_Link.bat | 1 + z_Setup.bat | 1 + 7 files changed, 127 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 BUILD.bat create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 z_Link.bat create mode 100644 z_Setup.bat 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..d010fc61 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# eclipse +bin +*.launch +.settings +.metadata +.classpath +.project + +# idea +out +*.ipr +*.iws +*.iml +.idea + +# gradle +build +.gradle +gradle + +# other +eclipse +run +gradlew +gradlew.bat \ 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/build.gradle b/build.gradle new file mode 100644 index 00000000..fd19fc68 --- /dev/null +++ b/build.gradle @@ -0,0 +1,77 @@ +buildscript { + repositories { + jcenter() + maven { url = "http://files.minecraftforge.net/maven" } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:2.2-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.11.2" +archivesBaseName = "Sound-Physics" + +jar { + manifest { + attributes 'FMLCorePlugin': 'com.sonicether.soundphysics.SPFMLLoadingPlugin' + attributes 'FMLCorePluginContainsFMLMod': 'true' + } +} + +minecraft { + version = "1.11.2-13.20.0.2201" + runDir = "run" + + // the mappings can be changed at any time, and must be in the following format. + // snapshot_YYYYMMDD snapshot are built nightly. + // stable_# stables are built at the discretion of the MCP team. + // Use non-default mappings at your own risk. they may not always work. + // simply re-run your setup task after changing the mappings to update your workspace. + mappings = "snapshot_20161220" + // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. +} + +dependencies { + // you may put jars on which you depend on in ./libs + // or you may define them like so.. + //compile "some.group:artifact:version:classifier" + //compile "some.group:artifact:version" + + // real examples + //compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env + //compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env + + // the 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. + //provided 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // the deobf configurations: 'deobfCompile' and 'deobfProvided' are the same as the normal compile and provided, + // except that these dependencies get remapped to your current MCP mappings + //deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev' + //deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // for more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html + +} + +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' + } +} \ No newline at end of file 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/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 From 90f628c8903930e30d16a726e6f8883fe41dfdd0 Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 5 Apr 2017 22:40:41 +0200 Subject: [PATCH 02/39] .player and .world and clamp due to new mappings --- .../sonicether/soundphysics/SoundPhysics.java | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 2eb8f5b9..941287c5 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -230,7 +230,7 @@ public static double calculateEntitySoundOffset(Entity entity, SoundEvent sound) private static float getBlockReflectivity(Int3 blockPos) { - Block block = mc.theWorld.getBlockState(new BlockPos(blockPos.x, blockPos.y, blockPos.z)).getBlock(); + Block block = mc.world.getBlockState(new BlockPos(blockPos.x, blockPos.y, blockPos.z)).getBlock(); SoundType soundType = block.getSoundType(); float reflectivity = 0.5f; @@ -355,10 +355,10 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl } - if (mc.thePlayer == null) + if (mc.player == null) return; - if (mc.theWorld == null) + if (mc.world == null) return; if (SoundPhysicsCore.Config.skipRainOcclusionTracing && lastSoundName.matches(".*rain.*")) @@ -373,8 +373,8 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl //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); + Vec3d playerPos = mc.player.getPositionVector(); + playerPos = new Vec3d(playerPos.xCoord, playerPos.yCoord + mc.player.getEyeHeight(), playerPos.zCoord); soundPos = offsetSoundByName(soundPos, playerPos, lastSoundName, lastSoundCategory.getName()); @@ -403,7 +403,7 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl for(int i = 0; i < 10; i++) { - RayTraceResult rayHit = mc.theWorld.rayTraceBlocks(rayOrigin, playerPos, true); + RayTraceResult rayHit = mc.world.rayTraceBlocks(rayOrigin, playerPos, true); //If we hit a block if (rayHit != null) @@ -416,8 +416,8 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl //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(); + //Block blockHit = mc.world.getBlock(rayHit.blockX, rayHit.blockY, rayHit.blockZ); + Block blockHit = mc.world.getBlockState(rayHit.getBlockPos()).getBlock(); float blockOcclusion = 1.0f; @@ -475,7 +475,7 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl float sendCutoff3 = 1.0f; - if (mc.thePlayer.isInsideOfMaterial(Material.WATER)) + if (mc.player.isInsideOfMaterial(Material.WATER)) { directCutoff *= 1.0f - SoundPhysicsCore.Config.underwaterFilter; } @@ -539,7 +539,7 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl 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); + RayTraceResult rayHit = mc.world.rayTraceBlocks(rayStart, rayEnd, true); if (rayHit != null) { @@ -569,7 +569,7 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl //log("New ray dir: " + newRayDir.xCoord + ", " + newRayDir.yCoord + ", " + newRayDir.zCoord); - RayTraceResult newRayHit = mc.theWorld.rayTraceBlocks(newRayStart, newRayEnd, true); + RayTraceResult newRayHit = mc.world.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); @@ -610,7 +610,7 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl 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); + RayTraceResult finalRayHit = mc.world.rayTraceBlocks(finalRayStart, playerPos, true); if (finalRayHit == null) { @@ -626,11 +626,11 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl 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 cross0 = 1.0f - MathHelper.clamp(Math.abs(reflectionDelay - 0.0f), 0.0f, 1.0f); + float cross1 = 1.0f - MathHelper.clamp(Math.abs(reflectionDelay - 1.0f), 0.0f, 1.0f); + float cross2 = 1.0f - MathHelper.clamp(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); + float cross3 = MathHelper.clamp(reflectionDelay - 2.0f, 0.0f, 1.0f); /* 1.0 / numRays*/ sendGain0 += cross0 * energyTowardsPlayer * 6.4f * rcpTotalRays; sendGain1 += cross1 * energyTowardsPlayer * 12.8f * rcpTotalRays; @@ -644,7 +644,7 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl } } - //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."); + //log("Hit " + mc.world.getBlock(rayHit.blockX, rayHit.blockY, rayHit.blockZ).getUnlocalizedName() + " at " + rayHit.hitVec.xCoord + ", " + rayHit.hitVec.yCoord + ", " + rayHit.hitVec.zCoord + " and travelled " + rayLength + " meters."); } else { @@ -680,10 +680,10 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl 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); + float sharedAirspaceWeight0 = MathHelper.clamp(sharedAirspace / 20.0f, 0.0f, 1.0f); + float sharedAirspaceWeight1 = MathHelper.clamp(sharedAirspace / 15.0f, 0.0f, 1.0f); + float sharedAirspaceWeight2 = MathHelper.clamp(sharedAirspace / 10.0f, 0.0f, 1.0f); + float sharedAirspaceWeight3 = MathHelper.clamp(sharedAirspace / 10.0f, 0.0f, 1.0f); sendCutoff0 = (float)Math.exp(-occlusionAccumulation * absorptionCoeff * 1.0f) * (1.0f - sharedAirspaceWeight0) + sharedAirspaceWeight0; @@ -726,10 +726,10 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl 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 = MathHelper.clamp(sendGain0 * 1.00f - 0.00f, 0.0f, 1.0f); + sendGain1 = MathHelper.clamp(sendGain1 * 1.00f - 0.00f, 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); @@ -751,7 +751,7 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl //sendGain2 = 0.0f; //sendGain3 = 0.0f; - if (mc.thePlayer.isInWater()) + if (mc.player.isInWater()) { sendCutoff0 *= 0.4f; sendCutoff1 *= 0.4f; @@ -823,9 +823,9 @@ private static void setEnvironment(int sourceID, float sendGain0, float sendGain private static float calculateAttenuation(double x, double y, double z) { - if (SoundPhysics.mc.thePlayer != null) + if (SoundPhysics.mc.player != null) { - Vec3d playerPos = SoundPhysics.mc.thePlayer.getPositionVector(); + Vec3d playerPos = SoundPhysics.mc.player.getPositionVector(); double soundDistance = playerPos.distanceTo(new Vec3d(x, y, z)); @@ -957,7 +957,7 @@ protected static boolean checkErrorLog(String errorMessage) //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) + if (mc.player != null) { double distance = getDistanceFromPlayer(posX, posY, posZ); return distance < 32.0; @@ -967,9 +967,9 @@ public static boolean shouldSoundPacketBeSent(double posX, double posY, double p 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; + double x = mc.player.posX - posX; + double y = mc.player.posY - posY; + double z = mc.player.posZ - posZ; x *= x; y *= y; From d2ad69f2f25d6d5fc4df821b26aecea161f655dd Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 5 Apr 2017 22:48:21 +0200 Subject: [PATCH 03/39] Cleanup some of the unnecessary code --- .../sonicether/soundphysics/ReverbParams.java | 2 - .../sonicether/soundphysics/SPConfigGUI.java | 3 +- .../sonicether/soundphysics/SPGUIFactory.java | 2 - .../sonicether/soundphysics/SoundPhysics.java | 84 ++----------------- .../soundphysics/SoundPhysicsCore.java | 7 -- 5 files changed, 8 insertions(+), 90 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/ReverbParams.java b/src/main/java/com/sonicether/soundphysics/ReverbParams.java index 0d6d2fee..2905a28c 100644 --- a/src/main/java/com/sonicether/soundphysics/ReverbParams.java +++ b/src/main/java/com/sonicether/soundphysics/ReverbParams.java @@ -1,7 +1,5 @@ package com.sonicether.soundphysics; -import org.lwjgl.openal.EFX10; - public class ReverbParams { public float decayTime; // min: 0.1f max: 10.0f diff --git a/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java b/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java index c5f37193..f724603e 100644 --- a/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java +++ b/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java @@ -4,7 +4,6 @@ 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; @@ -25,7 +24,7 @@ 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(Configuration.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")); diff --git a/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java b/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java index 66a8646a..37948b54 100644 --- a/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java +++ b/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java @@ -5,8 +5,6 @@ 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 diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 941287c5..bfbc0ffe 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -1,8 +1,11 @@ package com.sonicether.soundphysics; -import java.nio.ByteBuffer; -import java.nio.IntBuffer; -import java.util.ArrayList; +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; @@ -21,14 +24,6 @@ import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3i; - -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 paulscode.sound.SoundSystemConfig; public class SoundPhysics @@ -91,16 +86,6 @@ public static void applyConfigChanges() } - 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 @@ -377,9 +362,7 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl playerPos = new Vec3d(playerPos.xCoord, playerPos.yCoord + mc.player.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(); @@ -395,9 +378,6 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl 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; float occlusionAccumulation = 0.0f; @@ -408,7 +388,6 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl //If we hit a block if (rayHit != null) { - numOcclusionHits++; //Get the normal of the side hit //Vec3d hitNormal = getNormalFromFacing(rayHit.sideHit); @@ -448,7 +427,6 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl //cutoff = 0.05f; thisHitSolid = !thisHitSolid; - firstHit = false; } else { @@ -495,17 +473,9 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl final int numRays = SoundPhysicsCore.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]; float sharedAirspace = 0.0f; @@ -544,9 +514,6 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl 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()); @@ -561,7 +528,6 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl //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); @@ -571,7 +537,6 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl RayTraceResult newRayHit = mc.world.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 energyTowardsPlayer = 0.25f; float blockReflectivity = getBlockReflectivity(lastHitBlock); @@ -579,7 +544,6 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl float bounceToPlayerDistance = (float)lastHitPos.distanceTo(playerPos); //energyTowardsPlayer *= 1.0f / ((float)Math.pow(bounceToPlayerDistance, 2.0) + 0.01f); - totalReflectivityRatio += blockReflectivity; if (newRayHit != null) { @@ -590,9 +554,6 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl } double newRayLength = lastHitPos.distanceTo(newRayHit.hitVec); - secondaryRayLengthSum += newRayLength; - secondaryReflectionEnergySum = 0.0f; - secondaryRayHits++; rayHits[j]++; bounceReflectivityRatio[j] += (float)Math.pow(blockReflectivity, reflectionEnergyCurve); @@ -607,7 +568,6 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl //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.world.rayTraceBlocks(finalRayStart, playerPos, true); @@ -653,19 +613,9 @@ private static void evaluateEnvironment(int sourceID, float posX, float posY, fl } - 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); @@ -821,26 +771,6 @@ private static void setEnvironment(int sourceID, float sendGain0, float sendGain } - private static float calculateAttenuation(double x, double y, double z) - { - if (SoundPhysics.mc.player != null) - { - Vec3d playerPos = SoundPhysics.mc.player.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; - } - } /** diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java index af708867..4fac0d01 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java @@ -463,13 +463,11 @@ private byte[] patchMethodInClass(String currentClassName, byte[] bytes, String[ //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)) @@ -479,15 +477,12 @@ private byte[] patchMethodInClass(String currentClassName, byte[] bytes, String[ 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) @@ -504,7 +499,6 @@ private byte[] patchMethodInClass(String currentClassName, byte[] bytes, String[ { log("Found target method invocation for injection: " + targetInvocationMethodName); targetNode = currentNode; - targetIndex = index; } } @@ -516,7 +510,6 @@ private byte[] patchMethodInClass(String currentClassName, byte[] bytes, String[ { log("Found target node for injection: " + targetNodeOpcode); targetNode = currentNode; - targetIndex = index; } } From 508815bdd027d9598c59f2fc4bf58cb58b355595 Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 5 Apr 2017 22:49:12 +0200 Subject: [PATCH 04/39] Unneeded class This mod needs a lot of clean up! --- .../soundphysics/ModSoundPhysics.java | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 src/main/java/com/sonicether/soundphysics/ModSoundPhysics.java 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 From f2850d32a0b5755645c92d280c9dd3515fb21a7b Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 5 Apr 2017 22:52:04 +0200 Subject: [PATCH 05/39] Remove unsafe event registering, access event bus properly Woah, git does not even see my changes properly... --- .../java/com/sonicether/soundphysics/SoundPhysicsCore.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java index 4fac0d01..bd582ad4 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java @@ -22,6 +22,7 @@ //import cpw.mods.fml.common.event.FMLPreInitializationEvent; //import cpw.mods.fml.common.eventhandler.SubscribeEvent; import net.minecraft.launchwrapper.IClassTransformer; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.fml.client.event.ConfigChangedEvent; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -35,8 +36,6 @@ 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"; @@ -96,7 +95,7 @@ public void preInit(FMLPreInitializationEvent event) @Mod.EventHandler public void init(FMLInitializationEvent event) { - FMLCommonHandler.instance().bus().register(instance); + MinecraftForge.EVENT_BUS.register(this); } @SubscribeEvent From 5b3cc6eebaeb58c2f2d837b1519887398b87fa55 Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 5 Apr 2017 22:55:58 +0200 Subject: [PATCH 06/39] Just patch in my previous bytecode edited update --- .../soundphysics/SoundPhysicsCore.java | 301 ++++-------------- 1 file changed, 63 insertions(+), 238 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java index bd582ad4..740f5764 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java @@ -158,245 +158,70 @@ private void log(String 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) + @Override public byte[] transform(String paramString1, String paramString2, byte[] paramArrayOfByte) { - //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; + InsnList localInsnList1 = new InsnList(); + localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "init", "()V")); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.client.audio.SoundManager$SoundSystemStarterThread", "ccq$a" }, new String[] { "", "" }, new String[] { "(Lnet/minecraft/client/audio/SoundManager;)V", "(Lccq;)V" }, 183, 5, new String[] { "", "" }, null, new InsnList[] { localInsnList1, localInsnList1 }, false, 0, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new VarInsnNode(25, 7)); + localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundCategory", "(Lnet/minecraft/util/SoundCategory;)V")); + InsnList localInsnList2 = new InsnList(); + localInsnList2.add(new VarInsnNode(25, 7)); + localInsnList2.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundCategory", "(Lno;)V")); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 182, 5, new String[] { "setVolume", "setVolume" }, null, new InsnList[] { localInsnList1, localInsnList2 }, false, 0, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new VarInsnNode(25, 1)); + localInsnList1.add(new MethodInsnNode(185, "net/minecraft/client/audio/ISound", "getSoundLocation", "()Lnet/minecraft/util/ResourceLocation;")); + localInsnList1.add(new MethodInsnNode(182, "net/minecraft/util/ResourceLocation", "toString", "()Ljava/lang/String;")); + localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", "(Ljava/lang/String;)V")); + localInsnList2 = new InsnList(); + localInsnList2.add(new VarInsnNode(25, 1)); + localInsnList2.add(new MethodInsnNode(185, "ccc", "a", "()Lkq;")); + localInsnList2.add(new MethodInsnNode(182, "kq", "toString", "()Ljava/lang/String;")); + localInsnList2.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", "(Ljava/lang/String;)V")); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 182, 5, new String[] { "setVolume", "setVolume" }, null, new InsnList[] { localInsnList1, localInsnList2 }, false, 0, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "globalVolumeMultiplier", "F")); + localInsnList1.add(new InsnNode(106)); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 183, 5, new String[] { "getClampedVolume", "e" }, new String[] { "(Lnet/minecraft/client/audio/ISound;)F", "(Lccc;)F" }, new InsnList[] { localInsnList1 }, false, 0, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new VarInsnNode(25, 0)); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", "Lpaulscode/sound/Vector3D;")); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "x", "F")); + localInsnList1.add(new VarInsnNode(25, 0)); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", "Lpaulscode/sound/Vector3D;")); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "y", "F")); + localInsnList1.add(new VarInsnNode(25, 0)); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", "Lpaulscode/sound/Vector3D;")); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "z", "F")); + localInsnList1.add(new VarInsnNode(25, 0)); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "channelOpenAL", "Lpaulscode/sound/libraries/ChannelLWJGLOpenAL;")); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/ChannelLWJGLOpenAL", "ALSource", "Ljava/nio/IntBuffer;")); + localInsnList1.add(new InsnNode(3)); + localInsnList1.add(new MethodInsnNode(182, "java/nio/IntBuffer", "get", "(I)I", false)); + localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "onPlaySound", "(FFFI)V", false)); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "paulscode.sound.libraries.SourceLWJGLOpenAL" }, new String[] { "play" }, new String[] { "(Lpaulscode/sound/Channel;)V" }, 182, 5, new String[] { "play" }, null, new InsnList[] { localInsnList1 }, false, 0, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "attenuationModel", "I")); + localInsnList1.add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "globalRolloffFactor", "F")); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "paulscode.sound.SoundSystem" }, new String[] { "newSource" }, new String[] { "(ZLjava/lang/String;Ljava/net/URL;Ljava/lang/String;ZFFFIF)V" }, 183, 5, new String[] { "" }, null, new InsnList[] { localInsnList1 }, true, 2, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "soundDistanceAllowance", "D")); + localInsnList1.add(new InsnNode(107)); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.server.management.PlayerList", "mt" }, new String[] { "sendToAllNearExcept", "a" }, new String[] { "(Lnet/minecraft/entity/player/EntityPlayer;DDDDILnet/minecraft/network/Packet;)V", "(Laay;DDDDILfm;)V" }, 152, 0, new String[] { "", "" }, new String[] { "", "" }, new InsnList[] { localInsnList1 }, true, 0, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new VarInsnNode(25, 1)); + localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "calculateEntitySoundOffset", "(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/SoundEvent;)D", false)); + localInsnList1.add(new InsnNode(99)); + localInsnList1.add(new VarInsnNode(25, 0)); + localInsnList2 = new InsnList(); + localInsnList2.add(new VarInsnNode(25, 1)); + localInsnList2.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "calculateEntitySoundOffset", "(Lsn;Lnm;)D", false)); + localInsnList2.add(new InsnNode(99)); + localInsnList2.add(new VarInsnNode(25, 0)); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.entity.Entity", "sn" }, new String[] { "playSound", "a" }, new String[] { "(Lnet/minecraft/util/SoundEvent;FF)V", "(Lnm;FF)V" }, 182, 5, new String[] { "getSoundCategory", "bC" }, null, new InsnList[] { localInsnList1, localInsnList2 }, true, 0, 0, false, -3); + return paramArrayOfByte; } /** From 8a4c46add4c30252a6decfe3450f964d6d7b9ae4 Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 5 Apr 2017 22:57:00 +0200 Subject: [PATCH 07/39] Target version 1.11.2 --- .../java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java | 2 +- src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java b/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java index a3824d43..9c9ec838 100644 --- a/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java +++ b/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java @@ -8,7 +8,7 @@ -@MCVersion(value="1.11") +@MCVersion(value="1.11.2") public class SPFMLLoadingPlugin implements IFMLLoadingPlugin, IFMLCallHook { diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java index 740f5764..eb33819e 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java @@ -4,7 +4,6 @@ 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; @@ -25,7 +24,6 @@ import net.minecraftforge.common.MinecraftForge; 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; From 501c2a8e7e5ac4300d99cd8263361e530293f6b8 Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 5 Apr 2017 23:02:31 +0200 Subject: [PATCH 08/39] Shrink classes, automatic cleanup --- .../sonicether/soundphysics/ClientProxy.java | 26 - .../sonicether/soundphysics/CommonProxy.java | 23 - .../com/sonicether/soundphysics/Int3.java | 29 +- .../sonicether/soundphysics/ReverbParams.java | 70 +- .../sonicether/soundphysics/SPConfigGUI.java | 49 +- .../soundphysics/SPDummyContainer.java | 73 - .../soundphysics/SPFMLLoadingPlugin.java | 23 +- .../sonicether/soundphysics/SPGUIFactory.java | 11 +- .../sonicether/soundphysics/ServerProxy.java | 23 - .../sonicether/soundphysics/SoundPhysics.java | 1323 +++++++++-------- .../soundphysics/SoundPhysicsCore.java | 561 ++++--- src/main/resources/mcmod.info | 2 +- 12 files changed, 1103 insertions(+), 1110 deletions(-) delete mode 100644 src/main/java/com/sonicether/soundphysics/ClientProxy.java delete mode 100644 src/main/java/com/sonicether/soundphysics/CommonProxy.java delete mode 100644 src/main/java/com/sonicether/soundphysics/SPDummyContainer.java delete mode 100644 src/main/java/com/sonicether/soundphysics/ServerProxy.java 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/Int3.java b/src/main/java/com/sonicether/soundphysics/Int3.java index c8af31e1..db89a12d 100644 --- a/src/main/java/com/sonicether/soundphysics/Int3.java +++ b/src/main/java/com/sonicether/soundphysics/Int3.java @@ -1,30 +1,27 @@ package com.sonicether.soundphysics; -public class Int3 -{ +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(); - + + public static Int3 create(final int x, final int y, final int z) { + final 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; + + @Override + public boolean equals(final Object b) { + final Int3 i = (Int3) b; return (this.x == i.x && this.y == i.y && this.z == i.z); } - - Int3() - { - + + Int3() { + } } diff --git a/src/main/java/com/sonicether/soundphysics/ReverbParams.java b/src/main/java/com/sonicether/soundphysics/ReverbParams.java index 2905a28c..cf650d59 100644 --- a/src/main/java/com/sonicether/soundphysics/ReverbParams.java +++ b/src/main/java/com/sonicether/soundphysics/ReverbParams.java @@ -1,23 +1,21 @@ package com.sonicether.soundphysics; -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 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() { + final ReverbParams r = new ReverbParams(); r.decayTime = 0.15f; r.density = 0.0f; r.diffusion = 1.0f; @@ -30,13 +28,12 @@ public static ReverbParams getReverb0() r.lateReverbDelay = 0.011f; r.airAbsorptionGainHF = 0.994f; r.roomRolloffFactor = 0.16f * SoundPhysicsCore.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; @@ -49,13 +46,12 @@ public static ReverbParams getReverb1() r.lateReverbDelay = 0.011f; r.airAbsorptionGainHF = 0.994f; r.roomRolloffFactor = 0.15f * SoundPhysicsCore.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; @@ -68,13 +64,12 @@ public static ReverbParams getReverb2() r.lateReverbDelay = 0.021f; r.airAbsorptionGainHF = 0.994f; r.roomRolloffFactor = 0.13f * SoundPhysicsCore.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; @@ -87,12 +82,11 @@ public static ReverbParams getReverb3() r.lateReverbDelay = 0.021f; r.airAbsorptionGainHF = 0.994f; r.roomRolloffFactor = 0.11f * SoundPhysicsCore.Config.rolloffFactor; - + return r; } - - ReverbParams() - { - + + ReverbParams() { + } } diff --git a/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java b/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java index f724603e..1cf4efe8 100644 --- a/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java +++ b/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java @@ -11,31 +11,32 @@ import net.minecraftforge.fml.client.config.GuiConfig; import net.minecraftforge.fml.client.config.IConfigElement; -public class SPConfigGUI extends GuiConfig -{ - public SPConfigGUI(GuiScreen parent) - { +public class SPConfigGUI extends GuiConfig { + public SPConfigGUI(final 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(Configuration.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()); - } + private static List getConfigElements() { + final List list = new ArrayList<>(); + + // Add categories to config GUI + list.add(categoryElement(Configuration.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(final String category, final String name, final 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 index 9c9ec838..e9d73473 100644 --- a/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java +++ b/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java @@ -6,21 +6,17 @@ import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.MCVersion; - - -@MCVersion(value="1.11.2") -public class SPFMLLoadingPlugin implements IFMLLoadingPlugin, IFMLCallHook -{ +@MCVersion(value = "1.11.2") +public class SPFMLLoadingPlugin implements IFMLLoadingPlugin, IFMLCallHook { @Override - public String[] getASMTransformerClass() - { - return new String[]{SoundPhysicsCore.class.getName()}; + public String[] getASMTransformerClass() { + return new String[] { SoundPhysicsCore.class.getName() }; } @Override public String getModContainerClass() { - //return SPDummyContainer.class.getName(); + // return SPDummyContainer.class.getName(); return null; } @@ -30,9 +26,9 @@ public String getSetupClass() { } @Override - public void injectData(Map data) { + public void injectData(final Map data) { // TODO Auto-generated method stub - + } @Override @@ -40,12 +36,13 @@ 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. + // 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 index 37948b54..8788baa9 100644 --- a/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java +++ b/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java @@ -6,14 +6,12 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraftforge.fml.client.IModGuiFactory; - -public class SPGUIFactory implements IModGuiFactory -{ +public class SPGUIFactory implements IModGuiFactory { @Override - public void initialize(Minecraft minecraftInstance) { + public void initialize(final Minecraft minecraftInstance) { // TODO Auto-generated method stub - + } @Override @@ -28,8 +26,7 @@ public Set runtimeGuiCategories() { } @Override - public RuntimeOptionGuiHandler getHandlerFor( - RuntimeOptionCategoryElement element) { + public RuntimeOptionGuiHandler getHandlerFor(final RuntimeOptionCategoryElement element) { // TODO Auto-generated method stub 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 bfbc0ffe..a5eeecc9 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -26,9 +26,8 @@ import net.minecraft.util.math.Vec3i; import paulscode.sound.SoundSystemConfig; -public class SoundPhysics -{ - //Private fields +public class SoundPhysics { + // Private fields private static final String logPrefix = "[SOUND PHYSICS]"; private static int auxFXSlot0; private static int auxFXSlot1; @@ -43,868 +42,956 @@ 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 + + // Public fields public static int attenuationModel = SoundSystemConfig.ATTENUATION_ROLLOFF; public static float globalRolloffFactor = SoundPhysicsCore.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() - { + + public static void init() { log("Initializing Sound Physics..."); setupEFX(); mc = Minecraft.getMinecraft(); } - - - public static void applyConfigChanges() - { + + 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 + + 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 } - + } - - - 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 + + // 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 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(); // Create effect object + EFX10.alEffecti(reverb1, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_EAXREVERB); // Set + // effect + // object + // to + // be + // reverb 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(); // Create effect object + EFX10.alEffecti(reverb2, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_EAXREVERB); // Set + // effect + // object + // to + // be + // reverb 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(); // Create effect object + EFX10.alEffecti(reverb3, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_EAXREVERB); // Set + // effect + // object + // to + // be + // reverb 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 + + // 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"); + + public static void setLastSoundCategory(final SoundCategory sc) { + // log("Set last sound category"); lastSoundCategory = sc; } - - public static void setLastSoundName(String name) - { - //log("Set last sound name: " + name); + + public static void setLastSoundName(final String name) { + // log("Set last sound name: " + 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); - + + public static void onPlaySound(final float posX, final float posY, final float posZ, final 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) + + if (SoundPhysicsCore.Config.performanceLogging) { startTime = System.nanoTime(); - + } + evaluateEnvironment(sourceID, posX, posY, posZ); - - if (SoundPhysicsCore.Config.performanceLogging) - { + + if (SoundPhysicsCore.Config.performanceLogging) { endTime = System.nanoTime(); - log("Total calculation time for sound " + lastSoundName + ": " + (double)(endTime - startTime)/(double)1000000 + " milliseconds"); + log("Total calculation time for sound " + lastSoundName + ": " + + (double) (endTime - startTime) / (double) 1000000 + " milliseconds"); } - - - //System.out.println(soundCategory.getCategoryName()); + + // 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()); + + public static double calculateEntitySoundOffset(final Entity entity, final SoundEvent sound) { + if (!sound.getSoundName().getResourcePath().matches(".*step.*")) { + // log("Offset entity say sound by " + entity.getEyeHeight()); return entity.getEyeHeight(); - } - else - { + } else { return 0.0; } - //return 0.0; + // return 0.0; } - - private static float getBlockReflectivity(Int3 blockPos) - { - Block block = mc.world.getBlockState(new BlockPos(blockPos.x, blockPos.y, blockPos.z)).getBlock(); - SoundType soundType = block.getSoundType(); - + + private static float getBlockReflectivity(final Int3 blockPos) { + final Block block = mc.world.getBlockState(new BlockPos(blockPos.x, blockPos.y, blockPos.z)).getBlock(); + final SoundType soundType = block.getSoundType(); + float reflectivity = 0.5f; - - if (soundType == SoundType.STONE) + + if (soundType == SoundType.STONE) { reflectivity = SoundPhysicsCore.Config.stoneReflectivity; - else if (soundType == SoundType.WOOD) + } else if (soundType == SoundType.WOOD) { reflectivity = SoundPhysicsCore.Config.woodReflectivity; - else if (soundType == SoundType.GROUND) + } else if (soundType == SoundType.GROUND) { reflectivity = SoundPhysicsCore.Config.groundReflectivity; - else if (soundType == SoundType.PLANT) + } else if (soundType == SoundType.PLANT) { reflectivity = SoundPhysicsCore.Config.plantReflectivity; - else if (soundType == SoundType.METAL) + } else if (soundType == SoundType.METAL) { reflectivity = SoundPhysicsCore.Config.metalReflectivity; - else if (soundType == SoundType.GLASS) + } else if (soundType == SoundType.GLASS) { reflectivity = SoundPhysicsCore.Config.glassReflectivity; - else if (soundType == SoundType.CLOTH) + } else if (soundType == SoundType.CLOTH) { reflectivity = SoundPhysicsCore.Config.clothReflectivity; - else if (soundType == SoundType.SAND) + } else if (soundType == SoundType.SAND) { reflectivity = SoundPhysicsCore.Config.sandReflectivity; - else if (soundType == SoundType.SNOW) + } else if (soundType == SoundType.SNOW) { reflectivity = SoundPhysicsCore.Config.snowReflectivity; - else if (soundType == SoundType.LADDER) + } else if (soundType == SoundType.LADDER) { reflectivity = SoundPhysicsCore.Config.woodReflectivity; - else if (soundType == SoundType.ANVIL) + } else if (soundType == SoundType.ANVIL) { reflectivity = SoundPhysicsCore.Config.metalReflectivity; - + } + reflectivity *= SoundPhysicsCore.Config.globalBlockReflectance; - + return reflectivity; } - - private static Vec3d getNormalFromFacing(EnumFacing sideHit) - { + + private static Vec3d getNormalFromFacing(final 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; - 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(); - + + final Vec3i inormal = sideHit.getDirectionVec(); + normal = new Vec3d(inormal.getX(), inormal.getY(), inormal.getZ()); - + return normal; } - - 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) { + // dir - 2.0 * dot(normal, dir) * normal + final double dot = dir.dotProduct(normal); + + final double x = dir.xCoord - 2.0 * dot * normal.xCoord; + final double y = dir.yCoord - 2.0 * dot * normal.yCoord; + final double z = dir.zCoord - 2.0 * dot * normal.zCoord; + return new Vec3d(x, y, z); } - - private static Vec3d offsetSoundByName(Vec3d soundPos, Vec3d playerPos, String name, String soundCategory) - { + + private static Vec3d offsetSoundByName(Vec3d soundPos, final Vec3d playerPos, final String name, + final String soundCategory) { 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.*")) - { + + final Vec3d toPlayerVector = playerPos.subtract(soundPos).normalize(); + + // names + if (name.matches(".*step.*")) { offsetY = 0.1; } - - //categories - if (soundCategory.matches("block") || soundCategory.matches("record")) - { + + // categories + if (soundCategory.matches("block") || soundCategory.matches("record")) { offsetTowardsPlayer = 0.89; } - - if (soundPos.yCoord % 1.0 < 0.001 && soundPos.yCoord > 0.01) - { + + if (soundPos.yCoord % 1.0 < 0.001 && soundPos.yCoord > 0.01) { offsetY = 0.1; } - + offsetX += toPlayerVector.xCoord * offsetTowardsPlayer; offsetY += toPlayerVector.yCoord * offsetTowardsPlayer; offsetZ += toPlayerVector.zCoord * offsetTowardsPlayer; - - //soundPos.xCoord += offsetX; - //soundPos.yCoord += offsetY; - //soundPos.zCoord += offsetZ; + + // soundPos.xCoord += offsetX; + // soundPos.yCoord += offsetY; + // soundPos.zCoord += offsetZ; soundPos = soundPos.addVector(offsetX, offsetY, offsetZ); - - //logDetailed("Offset sound by " + offsetX + ", " + offsetY + ", " + offsetZ); - + + // logDetailed("Offset sound by " + offsetX + ", " + offsetY + ", " + + // offsetZ); + return soundPos; } - - 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!"); - + + private static void evaluateEnvironment(final int sourceID, final float posX, final float posY, final float posZ) { + if (posX < 0.01f && posY < 0.01f && posZ < 0.01f) { + // logDetailed("Menu sound!"); + 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.player == null) + + if (mc.player == null) { return; - - if (mc.world == null) + } + + if (mc.world == null) { return; - - if (SoundPhysicsCore.Config.skipRainOcclusionTracing && lastSoundName.matches(".*rain.*")) - { + } + + if (SoundPhysicsCore.Config.skipRainOcclusionTracing && lastSoundName.matches(".*rain.*")) { 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 + final float absorptionCoeff = SoundPhysicsCore.Config.globalBlockAbsorption * 3.0f; + + // Direct sound occlusion Vec3d soundPos = new Vec3d(posX, posY, posZ); Vec3d playerPos = mc.player.getPositionVector(); - playerPos = new Vec3d(playerPos.xCoord, playerPos.yCoord + mc.player.getEyeHeight(), playerPos.zCoord); - + playerPos = new Vec3d(playerPos.xCoord, playerPos.yCoord + mc.player.getEyeHeight(), playerPos.zCoord); + soundPos = offsetSoundByName(soundPos, playerPos, lastSoundName, lastSoundCategory.getName()); - - //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 toPlayerVector = soundPos.subtract(playerPos).normalize(); + final 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.*")) - { + 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 thisHitSolid = false; // TODO: This will be true if the sound + // doesn't come from inside a block! + float occlusionAccumulation = 0.0f; - - for(int i = 0; i < 10; i++) - { - RayTraceResult rayHit = mc.world.rayTraceBlocks(rayOrigin, playerPos, true); - - //If we hit a block - if (rayHit != null) - { - //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.world.getBlock(rayHit.blockX, rayHit.blockY, rayHit.blockZ); - Block blockHit = mc.world.getBlockState(rayHit.getBlockPos()).getBlock(); - + + for (int i = 0; i < 10; i++) { + final RayTraceResult rayHit = mc.world.rayTraceBlocks(rayOrigin, playerPos, true); + + // If we hit a block + if (rayHit != null) { + // 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.world.getBlock(rayHit.blockX, + // rayHit.blockY, rayHit.blockZ); + final Block blockHit = mc.world.getBlockState(rayHit.getBlockPos()).getBlock(); + float blockOcclusion = 1.0f; - - if (!blockHit.isOpaqueCube(blockHit.getDefaultState())) - { - //log("not a solid block!"); + + 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 + + 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; - + // 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; - } - else - { - //System.out.println("Didn't hit anything!"); + } else { + // System.out.println("Didn't hit anything!"); break; } - + } - - directCutoff = (float)Math.exp(-occlusionAccumulation * absorptionCoeff); - float directGain = (float)Math.pow(directCutoff, 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 + + // 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.player.isInsideOfMaterial(Material.WATER)) - { + + if (mc.player.isInsideOfMaterial(Material.WATER)) { directCutoff *= 1.0f - SoundPhysicsCore.Config.underwaterFilter; } - - - if (lastSoundName.matches(".*rain.*")) - { - setEnvironment(sourceID, sendGain0, sendGain1, sendGain2, sendGain3, sendCutoff0, sendCutoff1, sendCutoff2, sendCutoff3, directCutoff, directGain); + + if (lastSoundName.matches(".*rain.*")) { + 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 rayBounces = 4; - - int[] rayHits = new int[rayBounces]; - - float[] bounceReflectivityRatio = new float[rayBounces]; - + + final int[] rayHits = new int[rayBounces]; + + final float[] bounceReflectivityRatio = new float[rayBounces]; + float sharedAirspace = 0.0f; - - float rcpTotalRays = 1.0f / (numRays * rayBounces); - float rcpPrimaryRays = 1.0f / (numRays); - + + final float rcpTotalRays = 1.0f / (numRays * rayBounces); + final 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); - + + for (int i = 0; i < numRays; i++) { + final float fi = i; + final float fiN = fi / numRays; + final float longitude = gAngle * fi * 1.0f; + final 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); + // 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); + final double x = Math.cos(latitude) * Math.cos(longitude); + final double y = Math.cos(latitude) * Math.sin(longitude); + final 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.world.rayTraceBlocks(rayStart, rayEnd, true); - - if (rayHit != null) - { - double rayLength = soundPos.distanceTo(rayHit.hitVec); - - //Additional bounces - Int3 lastHitBlock = Int3.create(rayHit.getBlockPos().getX(), rayHit.getBlockPos().getY(), rayHit.getBlockPos().getZ()); + + // Vec3d rayStart = Vec3d.createVectorHelper(soundPos.xCoord + + // rayDir.xCoord * 0.867, soundPos.yCoord + rayDir.yCoord * 0.867, + // soundPos.zCoord + rayDir.zCoord * 0.867); + final Vec3d rayStart = new Vec3d(soundPos.xCoord, soundPos.yCoord, soundPos.zCoord); + + final Vec3d rayEnd = new Vec3d(rayStart.xCoord + rayDir.xCoord * maxDistance, + rayStart.yCoord + rayDir.yCoord * maxDistance, rayStart.zCoord + rayDir.zCoord * maxDistance); + + final RayTraceResult rayHit = mc.world.rayTraceBlocks(rayStart, rayEnd, true); + + if (rayHit != null) { + final double rayLength = soundPos.distanceTo(rayHit.hitVec); + + // Additional bounces + Int3 lastHitBlock = Int3.create(rayHit.getBlockPos().getX(), rayHit.getBlockPos().getY(), + rayHit.getBlockPos().getZ()); 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++) - { - 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.world.rayTraceBlocks(newRayStart, newRayEnd, true); - - //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.xCoord + lastHitNormal.xCoord * 0.01, + lastHitPos.yCoord + lastHitNormal.yCoord * 0.01, + lastHitPos.zCoord + lastHitNormal.zCoord * 0.01); + final 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); + + final RayTraceResult newRayHit = mc.world.rayTraceBlocks(newRayStart, newRayEnd, true); + + // float energyTowardsPlayer = + // (float)Math.pow(MathHelper.clamp_float(soundDirToPlayerDot, + // 0.0f, 1.0f), 1.0f); 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); - - - 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; + final float blockReflectivity = getBlockReflectivity(lastHitBlock); + energyTowardsPlayer *= blockReflectivity * 0.75f + 0.25f; + final float bounceToPlayerDistance = (float) lastHitPos.distanceTo(playerPos); + // energyTowardsPlayer *= 1.0f / + // ((float)Math.pow(bounceToPlayerDistance, 2.0) + 0.01f); + + 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); + + final double newRayLength = lastHitPos.distanceTo(newRayHit.hitVec); rayHits[j]++; - bounceReflectivityRatio[j] += (float)Math.pow(blockReflectivity, reflectionEnergyCurve); - + bounceReflectivityRatio[j] += (float) Math.pow(blockReflectivity, reflectionEnergyCurve); + 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 finalRayStart = new Vec3d(lastHitPos.xCoord + lastHitNormal.xCoord * 0.01, lastHitPos.yCoord + lastHitNormal.yCoord * 0.01, lastHitPos.zCoord + lastHitNormal.zCoord * 0.01); - - RayTraceResult finalRayHit = mc.world.rayTraceBlocks(finalRayStart, playerPos, true); - - if (finalRayHit == null) - { - //log("Secondary ray hit the player!"); + 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) { + final Vec3d finalRayStart = new Vec3d(lastHitPos.xCoord + lastHitNormal.xCoord * 0.01, + lastHitPos.yCoord + lastHitNormal.yCoord * 0.01, + lastHitPos.zCoord + lastHitNormal.zCoord * 0.01); + + final RayTraceResult finalRayHit = mc.world.rayTraceBlocks(finalRayStart, playerPos, true); + + if (finalRayHit == null) { + // log("Secondary ray hit the player!"); sharedAirspace += 1.0f; } } - } - else - { + } 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(Math.abs(reflectionDelay - 0.0f), 0.0f, 1.0f); - float cross1 = 1.0f - MathHelper.clamp(Math.abs(reflectionDelay - 1.0f), 0.0f, 1.0f); - float cross2 = 1.0f - MathHelper.clamp(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(reflectionDelay - 2.0f, 0.0f, 1.0f); - -/* 1.0 / numRays*/ sendGain0 += cross0 * energyTowardsPlayer * 6.4f * rcpTotalRays; + + final float reflectionDelay = (float) Math.pow(Math.max(totalRayDistance, 0.0), 1.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); + // float cross3 = 1.0f - + // MathHelper.clamp_float(Math.abs(reflectionDelay - 3.0f), + // 0.0f, 1.0f); + final float cross3 = MathHelper.clamp(reflectionDelay - 2.0f, 0.0f, 1.0f); + + /* 1.0 / numRays */ 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.world.getBlock(rayHit.blockX, rayHit.blockY, rayHit.blockZ).getUnlocalizedName() + " at " + rayHit.hitVec.xCoord + ", " + rayHit.hitVec.yCoord + ", " + rayHit.hitVec.zCoord + " and travelled " + rayLength + " meters."); + // log("Hit " + mc.world.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"); } - else - { - //log("Escaped"); - } - + } - - - //log("total reflectivity ratio: " + totalReflectivityRatio); - - - 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] = (float) Math.pow(bounceReflectivityRatio[0] / numRays, + 1.0 / reflectionEnergyCurve); + bounceReflectivityRatio[1] = (float) Math.pow(bounceReflectivityRatio[1] / numRays, + 1.0 / reflectionEnergyCurve); + bounceReflectivityRatio[2] = (float) Math.pow(bounceReflectivityRatio[2] / numRays, + 1.0 / reflectionEnergyCurve); + bounceReflectivityRatio[3] = (float) Math.pow(bounceReflectivityRatio[3] / numRays, + 1.0 / reflectionEnergyCurve); + sharedAirspace *= 64.0f; - - if (SoundPhysicsCore.Config.simplerSharedAirspaceSimulation) + + if (SoundPhysicsCore.Config.simplerSharedAirspaceSimulation) { sharedAirspace *= rcpPrimaryRays; - else + } else { sharedAirspace *= rcpTotalRays; - - float sharedAirspaceWeight0 = MathHelper.clamp(sharedAirspace / 20.0f, 0.0f, 1.0f); - float sharedAirspaceWeight1 = MathHelper.clamp(sharedAirspace / 15.0f, 0.0f, 1.0f); - float sharedAirspaceWeight2 = MathHelper.clamp(sharedAirspace / 10.0f, 0.0f, 1.0f); - 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 - 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 + } + + 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); + + // 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); - */ - + * 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(sendGain0 * 1.00f - 0.00f, 0.0f, 1.0f); sendGain1 = MathHelper.clamp(sendGain1 * 1.00f - 0.00f, 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); - - - 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.player.isInWater()) - { + + 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.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); + * //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); } - - 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); } - - - - + /** - * 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) - { + protected static void setReverbParams(final ReverbParams r, final int auxFXSlot, final 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 + * 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 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); // Set + // default + // parameters 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); // Set + // default + // parameters 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); // Set + // default + // parameters 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); // Set + // default + // parameters 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); // Set + // default + // parameters 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); // Set + // default + // parameters 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); // Set + // default + // parameters 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); // Set + // default + // parameters 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); // Set + // default + // parameters 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); // Set + // default + // parameters 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) - { + + protected static void log(final String message) { System.out.println(logPrefix + ": " + message); } - - protected static void logOcclusion(String message) - { - if (!SoundPhysicsCore.Config.occlusionLogging) + + protected static void logOcclusion(final String message) { + if (!SoundPhysicsCore.Config.occlusionLogging) { return; - + } + System.out.println(logPrefix + " [OCCLUSION] " + ": " + message); } - - protected static void logEnvironment(String message) - { - if (!SoundPhysicsCore.Config.environmentLogging) + + protected static void logEnvironment(final String message) { + if (!SoundPhysicsCore.Config.environmentLogging) { return; - + } + System.out.println(logPrefix + " [ENVIRONMENT] " + ": " + message); } - - - protected static void logGeneral(String message) - { - if (!SoundPhysicsCore.Config.debugLogging) + + protected static void logGeneral(final String message) { + if (!SoundPhysicsCore.Config.debugLogging) { return; - + } + System.out.println(logPrefix + ": " + message); } - - - protected static void logError(String errorMessage) - { + + protected static void logError(final String errorMessage) { System.out.println(logPrefix + " [ERROR]: " + errorMessage); } - - protected static boolean checkErrorLog(String errorMessage) - { - int error = AL10.alGetError(); + + protected static boolean checkErrorLog(final String errorMessage) { + final 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; + + 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 - { + } else { 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.player != null) - { - double distance = getDistanceFromPlayer(posX, posY, posZ); + + // TODO: Find fancy way of determining if a sound is going to be + // sufficiently quiet to not play it. + public static boolean shouldSoundPacketBeSent(final double posX, final double posY, final double posZ, + final double volume) { + if (mc.player != null) { + final double distance = getDistanceFromPlayer(posX, posY, posZ); return distance < 32.0; + } else { + return false; } - else return false; } - - private static double getDistanceFromPlayer(double posX, double posY, double posZ) - { + + private static double getDistanceFromPlayer(final double posX, final double posY, final double posZ) { double x = mc.player.posX - posX; double y = mc.player.posY - posY; double z = mc.player.posZ - posZ; - + x *= x; y *= y; z *= z; - + return Math.sqrt(x + y + z); } } diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java index eb33819e..6ef345f4 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java @@ -30,19 +30,15 @@ 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 class SoundPhysicsCore implements IClassTransformer { public static Configuration configFile; - - + public static final String modid = "soundphysics"; public static final String version = "1.0.0"; - - - //Config variables - public static class Config - { - //general + + // 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; @@ -51,13 +47,13 @@ public static class Config public static float globalBlockReflectance = 1.0f; public static float airAbsorption = 1.0f; public static float underwaterFilter = 0.8f; - - //performance + + // performance public static boolean skipRainOcclusionTracing = true; public static int environmentEvaluationRays = 32; public static boolean simplerSharedAirspaceSimulation = false; - - //block properties + + // block properties public static float stoneReflectivity = 1.0f; public static float woodReflectivity = 0.4f; public static float groundReflectivity = 0.3f; @@ -67,328 +63,397 @@ public static class Config public static float clothReflectivity = 0.05f; public static float sandReflectivity = 0.2f; public static float snowReflectivity = 0.2f; - - //misc + + // 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) - { + public void preInit(final FMLPreInitializationEvent event) { configFile = new Configuration(event.getSuggestedConfigurationFile()); syncConfig(); } - + @Mod.EventHandler - public void init(FMLInitializationEvent event) - { + public void init(final FMLInitializationEvent event) { MinecraftForge.EVENT_BUS.register(this); } - + @SubscribeEvent - public void onConfigChanged(ConfigChangedEvent.OnConfigChangedEvent eventArgs) - { - if (eventArgs.getModID().equals(modid)) + public void onConfigChanged(final 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(); - } + + 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) + + private void log(final 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 paramString1, String paramString2, byte[] paramArrayOfByte) - { - InsnList localInsnList1 = new InsnList(); - localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "init", "()V")); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.client.audio.SoundManager$SoundSystemStarterThread", "ccq$a" }, new String[] { "", "" }, new String[] { "(Lnet/minecraft/client/audio/SoundManager;)V", "(Lccq;)V" }, 183, 5, new String[] { "", "" }, null, new InsnList[] { localInsnList1, localInsnList1 }, false, 0, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new VarInsnNode(25, 7)); - localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundCategory", "(Lnet/minecraft/util/SoundCategory;)V")); - InsnList localInsnList2 = new InsnList(); - localInsnList2.add(new VarInsnNode(25, 7)); - localInsnList2.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundCategory", "(Lno;)V")); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 182, 5, new String[] { "setVolume", "setVolume" }, null, new InsnList[] { localInsnList1, localInsnList2 }, false, 0, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new VarInsnNode(25, 1)); - localInsnList1.add(new MethodInsnNode(185, "net/minecraft/client/audio/ISound", "getSoundLocation", "()Lnet/minecraft/util/ResourceLocation;")); - localInsnList1.add(new MethodInsnNode(182, "net/minecraft/util/ResourceLocation", "toString", "()Ljava/lang/String;")); - localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", "(Ljava/lang/String;)V")); - localInsnList2 = new InsnList(); - localInsnList2.add(new VarInsnNode(25, 1)); - localInsnList2.add(new MethodInsnNode(185, "ccc", "a", "()Lkq;")); - localInsnList2.add(new MethodInsnNode(182, "kq", "toString", "()Ljava/lang/String;")); - localInsnList2.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", "(Ljava/lang/String;)V")); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 182, 5, new String[] { "setVolume", "setVolume" }, null, new InsnList[] { localInsnList1, localInsnList2 }, false, 0, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "globalVolumeMultiplier", "F")); - localInsnList1.add(new InsnNode(106)); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 183, 5, new String[] { "getClampedVolume", "e" }, new String[] { "(Lnet/minecraft/client/audio/ISound;)F", "(Lccc;)F" }, new InsnList[] { localInsnList1 }, false, 0, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new VarInsnNode(25, 0)); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", "Lpaulscode/sound/Vector3D;")); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "x", "F")); - localInsnList1.add(new VarInsnNode(25, 0)); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", "Lpaulscode/sound/Vector3D;")); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "y", "F")); - localInsnList1.add(new VarInsnNode(25, 0)); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", "Lpaulscode/sound/Vector3D;")); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "z", "F")); - localInsnList1.add(new VarInsnNode(25, 0)); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "channelOpenAL", "Lpaulscode/sound/libraries/ChannelLWJGLOpenAL;")); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/ChannelLWJGLOpenAL", "ALSource", "Ljava/nio/IntBuffer;")); - localInsnList1.add(new InsnNode(3)); - localInsnList1.add(new MethodInsnNode(182, "java/nio/IntBuffer", "get", "(I)I", false)); - localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "onPlaySound", "(FFFI)V", false)); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "paulscode.sound.libraries.SourceLWJGLOpenAL" }, new String[] { "play" }, new String[] { "(Lpaulscode/sound/Channel;)V" }, 182, 5, new String[] { "play" }, null, new InsnList[] { localInsnList1 }, false, 0, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "attenuationModel", "I")); - localInsnList1.add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "globalRolloffFactor", "F")); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "paulscode.sound.SoundSystem" }, new String[] { "newSource" }, new String[] { "(ZLjava/lang/String;Ljava/net/URL;Ljava/lang/String;ZFFFIF)V" }, 183, 5, new String[] { "" }, null, new InsnList[] { localInsnList1 }, true, 2, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "soundDistanceAllowance", "D")); - localInsnList1.add(new InsnNode(107)); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.server.management.PlayerList", "mt" }, new String[] { "sendToAllNearExcept", "a" }, new String[] { "(Lnet/minecraft/entity/player/EntityPlayer;DDDDILnet/minecraft/network/Packet;)V", "(Laay;DDDDILfm;)V" }, 152, 0, new String[] { "", "" }, new String[] { "", "" }, new InsnList[] { localInsnList1 }, true, 0, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new VarInsnNode(25, 1)); - localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "calculateEntitySoundOffset", "(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/SoundEvent;)D", false)); - localInsnList1.add(new InsnNode(99)); - localInsnList1.add(new VarInsnNode(25, 0)); - localInsnList2 = new InsnList(); - localInsnList2.add(new VarInsnNode(25, 1)); - localInsnList2.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "calculateEntitySoundOffset", "(Lsn;Lnm;)D", false)); - localInsnList2.add(new InsnNode(99)); - localInsnList2.add(new VarInsnNode(25, 0)); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, new String[] { "net.minecraft.entity.Entity", "sn" }, new String[] { "playSound", "a" }, new String[] { "(Lnet/minecraft/util/SoundEvent;FF)V", "(Lnm;FF)V" }, 182, 5, new String[] { "getSoundCategory", "bC" }, null, new InsnList[] { localInsnList1, localInsnList2 }, true, 0, 0, false, -3); - return paramArrayOfByte; + + // 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(final String paramString1, final String paramString2, byte[] paramArrayOfByte) { + InsnList localInsnList1 = new InsnList(); + localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "init", "()V")); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, + new String[] { "net.minecraft.client.audio.SoundManager$SoundSystemStarterThread", "ccq$a" }, + new String[] { "", "" }, + new String[] { "(Lnet/minecraft/client/audio/SoundManager;)V", "(Lccq;)V" }, 183, 5, + new String[] { "", "" }, null, new InsnList[] { localInsnList1, localInsnList1 }, false, 0, + 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new VarInsnNode(25, 7)); + localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundCategory", + "(Lnet/minecraft/util/SoundCategory;)V")); + InsnList localInsnList2 = new InsnList(); + localInsnList2.add(new VarInsnNode(25, 7)); + localInsnList2.add( + new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundCategory", "(Lno;)V")); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, + new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, + new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 182, 5, + new String[] { "setVolume", "setVolume" }, null, new InsnList[] { localInsnList1, localInsnList2 }, + false, 0, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new VarInsnNode(25, 1)); + localInsnList1.add(new MethodInsnNode(185, "net/minecraft/client/audio/ISound", "getSoundLocation", + "()Lnet/minecraft/util/ResourceLocation;")); + localInsnList1.add( + new MethodInsnNode(182, "net/minecraft/util/ResourceLocation", "toString", "()Ljava/lang/String;")); + localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", + "(Ljava/lang/String;)V")); + localInsnList2 = new InsnList(); + localInsnList2.add(new VarInsnNode(25, 1)); + localInsnList2.add(new MethodInsnNode(185, "ccc", "a", "()Lkq;")); + localInsnList2.add(new MethodInsnNode(182, "kq", "toString", "()Ljava/lang/String;")); + localInsnList2.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", + "(Ljava/lang/String;)V")); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, + new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, + new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 182, 5, + new String[] { "setVolume", "setVolume" }, null, new InsnList[] { localInsnList1, localInsnList2 }, + false, 0, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1 + .add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "globalVolumeMultiplier", "F")); + localInsnList1.add(new InsnNode(106)); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, + new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, + new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 183, 5, + new String[] { "getClampedVolume", "e" }, + new String[] { "(Lnet/minecraft/client/audio/ISound;)F", "(Lccc;)F" }, + new InsnList[] { localInsnList1 }, false, 0, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new VarInsnNode(25, 0)); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", + "Lpaulscode/sound/Vector3D;")); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "x", "F")); + localInsnList1.add(new VarInsnNode(25, 0)); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", + "Lpaulscode/sound/Vector3D;")); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "y", "F")); + localInsnList1.add(new VarInsnNode(25, 0)); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", + "Lpaulscode/sound/Vector3D;")); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "z", "F")); + localInsnList1.add(new VarInsnNode(25, 0)); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "channelOpenAL", + "Lpaulscode/sound/libraries/ChannelLWJGLOpenAL;")); + localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/ChannelLWJGLOpenAL", "ALSource", + "Ljava/nio/IntBuffer;")); + localInsnList1.add(new InsnNode(3)); + localInsnList1.add(new MethodInsnNode(182, "java/nio/IntBuffer", "get", "(I)I", false)); + localInsnList1.add( + new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "onPlaySound", "(FFFI)V", false)); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, + new String[] { "paulscode.sound.libraries.SourceLWJGLOpenAL" }, new String[] { "play" }, + new String[] { "(Lpaulscode/sound/Channel;)V" }, 182, 5, new String[] { "play" }, null, + new InsnList[] { localInsnList1 }, false, 0, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "attenuationModel", "I")); + localInsnList1 + .add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "globalRolloffFactor", "F")); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, + new String[] { "paulscode.sound.SoundSystem" }, new String[] { "newSource" }, + new String[] { "(ZLjava/lang/String;Ljava/net/URL;Ljava/lang/String;ZFFFIF)V" }, 183, 5, + new String[] { "" }, null, new InsnList[] { localInsnList1 }, true, 2, 0, false, 0); + localInsnList1 = new InsnList(); + localInsnList1 + .add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "soundDistanceAllowance", "D")); + localInsnList1.add(new InsnNode(107)); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, + new String[] { "net.minecraft.server.management.PlayerList", "mt" }, + new String[] { "sendToAllNearExcept", "a" }, + new String[] { "(Lnet/minecraft/entity/player/EntityPlayer;DDDDILnet/minecraft/network/Packet;)V", + "(Laay;DDDDILfm;)V" }, + 152, 0, new String[] { "", "" }, new String[] { "", "" }, new InsnList[] { localInsnList1 }, true, 0, 0, + false, 0); + localInsnList1 = new InsnList(); + localInsnList1.add(new VarInsnNode(25, 1)); + localInsnList1 + .add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "calculateEntitySoundOffset", + "(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/SoundEvent;)D", false)); + localInsnList1.add(new InsnNode(99)); + localInsnList1.add(new VarInsnNode(25, 0)); + localInsnList2 = new InsnList(); + localInsnList2.add(new VarInsnNode(25, 1)); + localInsnList2.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", + "calculateEntitySoundOffset", "(Lsn;Lnm;)D", false)); + localInsnList2.add(new InsnNode(99)); + localInsnList2.add(new VarInsnNode(25, 0)); + paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, + new String[] { "net.minecraft.entity.Entity", "sn" }, new String[] { "playSound", "a" }, + new String[] { "(Lnet/minecraft/util/SoundEvent;FF)V", "(Lnm;FF)V" }, 182, 5, + new String[] { "getSoundCategory", "bC" }, null, new InsnList[] { localInsnList1, localInsnList2 }, + true, 0, 0, false, -3); + return paramArrayOfByte; } - + /** - * - * @param currentClassName + * + * @param currentClassName * @param bytes - * @param targetClassNames {deobfuscatedName, obfuscatedName} - * @param targetMethodNames {deobfuscatedName, obfuscatedName} + * @param targetClassNames + * {deobfuscatedName, obfuscatedName} + * @param targetMethodNames + * {deobfuscatedName, obfuscatedName} * @param targetMethodSignature * @param targetNodeOpcode * @param targetNodeType - * @param targetInvocationMethodNames {deobfuscatedName, obfuscatedName} + * @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) - { + private byte[] patchMethodInClass(final String currentClassName, final byte[] bytes, + final String[] targetClassNames, final String[] targetMethodNames, final String[] targetMethodSignatures, + final int targetNodeOpcode, final int targetNodeType, final String[] targetInvocationMethodNames, + final String[] targetInvocationMethodSignatures, final InsnList[] instructionsToInjects, + final boolean insertBefore, final int nodesToDeleteBefore, final int nodesToDeleteAfter, + final boolean deleteTargetNode, final 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])) - { + + 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]; + 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) - { + if (targetInvocationMethodSignatures != null) { targetInvocationMethodSignature = targetInvocationMethodSignatures[0]; - if (obfuscated) - { - targetInvocationMethodSignature = targetInvocationMethodSignatures.length == 2 ? targetInvocationMethodSignatures[1] : targetInvocationMethodSignatures[0]; + if (obfuscated) { + targetInvocationMethodSignature = targetInvocationMethodSignatures.length == 2 + ? targetInvocationMethodSignatures[1] : targetInvocationMethodSignatures[0]; } } - - - //If this isn't the target class, leave! - if (!currentClassName.equals(targetClassName)) + + // 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); + + // Setup ASM class manipulation stuff + final ClassNode classNode = new ClassNode(); + final 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 - Iterator methods = classNode.methods.iterator(); - while(methods.hasNext()) - { - MethodNode m = methods.next(); + + // Now we loop over all of the methods declared inside the class until + // we get to the target method name + final Iterator methods = classNode.methods.iterator(); + while (methods.hasNext()) { + final MethodNode m = methods.next(); log("********* Method Name: " + m.name + " Desc: " + m.desc); - - //Check if this is the method name and the signature matches - if (m.name.equals(targetMethodName) && m.desc.equals(targetMethodSignature)) - { + + // 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; - - Iterator iter = m.instructions.iterator(); - - - //Loop over the instruction set - while (iter.hasNext()) - { + + final Iterator iter = m.instructions.iterator(); + + // Loop over the instruction set + while (iter.hasNext()) { currentNode = iter.next(); - - if (currentNode.getOpcode() == targetNodeOpcode) - { - if (targetNodeType == AbstractInsnNode.METHOD_INSN) //If we're looking for a method opcode + + 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); + if (currentNode.getType() == AbstractInsnNode.METHOD_INSN) { + final 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; } - + } } - } - else - { - if (currentNode.getType() == targetNodeType) - { + } else { + if (currentNode.getType() == targetNodeType) { log("Found target node for injection: " + targetNodeOpcode); targetNode = currentNode; } } - + } } - - //Offset the target node by the supplied offset value - if (targetNodeOffset > 0) - { - for (int i = 0; i < targetNodeOffset; i++) - { + + // 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++) - { + } 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! + + if (targetNode != null) // If we've found the target, inject the + // instructions! { - for (int i = 0; i < nodesToDeleteBefore; i++) - { - AbstractInsnNode previousNode = targetNode.getPrevious(); + for (int i = 0; i < nodesToDeleteBefore; i++) { + final AbstractInsnNode previousNode = targetNode.getPrevious(); log("Removing Node " + previousNode.getOpcode()); m.instructions.remove(previousNode); } - - for (int i = 0; i < nodesToDeleteAfter; i++) - { - AbstractInsnNode nextNode = targetNode.getNext(); + + for (int i = 0; i < nodesToDeleteAfter; i++) { + final AbstractInsnNode nextNode = targetNode.getNext(); log("Removing Node " + nextNode.getOpcode()); m.instructions.remove(nextNode); } - - - - if (insertBefore) + + if (insertBefore) { m.instructions.insertBefore(targetNode, instructionsToInject); - else + } else { m.instructions.insert(targetNode, instructionsToInject); - - if (deleteTargetNode) - { + } + + if (deleteTargetNode) { m.instructions.remove(targetNode); } - + log("Patching complete!----------------------------------------------------------------------------------------"); } break; } } - - ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); + + final 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..33caeb5b 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -4,7 +4,7 @@ "name": "Sound Physics", "description": "Provides realistic sound attenuation, reverberation, and absorption through blocks.", "version": "1.0.0", - "mcversion": "1.11", + "mcversion": "1.11.2", "url": "", "updateUrl": "", "authorList": ["Sonic Ether"], From 2c0f3e73d561de0ac0fe42502519014709287ee6 Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 5 Apr 2017 23:06:41 +0200 Subject: [PATCH 09/39] Make mod compliant with Java 1.6 --- src/main/java/com/sonicether/soundphysics/SPConfigGUI.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java b/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java index 1cf4efe8..63e2efd8 100644 --- a/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java +++ b/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java @@ -12,13 +12,14 @@ import net.minecraftforge.fml.client.config.IConfigElement; public class SPConfigGUI extends GuiConfig { + public SPConfigGUI(final GuiScreen parent) { super(parent, getConfigElements(), SoundPhysicsCore.modid, false, false, "Sound Physics Configuration"); } /** Compiles a list of config elements */ private static List getConfigElements() { - final List list = new ArrayList<>(); + final ArrayList list = new ArrayList(); // Add categories to config GUI list.add(categoryElement(Configuration.CATEGORY_GENERAL, "General", "soundphysics.configgui.ctgy.general")); @@ -39,4 +40,5 @@ private static IConfigElement categoryElement(final String category, final Strin return new DummyConfigElement.DummyCategoryElement(name, tooltip_key, new ConfigElement(SoundPhysicsCore.configFile.getCategory(category)).getChildElements()); } + } \ No newline at end of file From a9ba7a83132730e09339245a0fc269c12903abb5 Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 5 Apr 2017 23:09:24 +0200 Subject: [PATCH 10/39] Update README, sorry Sonic Ether, but it is true... --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ccb2c752..c04ef39b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # Sound-Physics A Minecraft mod that provides realistic sound attenuation, reverberation, and absorption through blocks. + +This is a fork! TODO: There is still some cleanup left! Sonic Ether's original source code was very messy! \ No newline at end of file From 61c0ac42afee846b54c0e3c01f2bd246a50a3829 Mon Sep 17 00:00:00 2001 From: daipenger Date: Thu, 6 Apr 2017 01:18:20 +0200 Subject: [PATCH 11/39] Remove Int3 (Used redundantly for BlockPos) --- .../com/sonicether/soundphysics/Int3.java | 27 ----- .../sonicether/soundphysics/SoundPhysics.java | 108 +++--------------- 2 files changed, 19 insertions(+), 116 deletions(-) delete mode 100644 src/main/java/com/sonicether/soundphysics/Int3.java 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 db89a12d..00000000 --- a/src/main/java/com/sonicether/soundphysics/Int3.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.sonicether.soundphysics; - -public class Int3 { - public int x; - public int y; - public int z; - - public static Int3 create(final int x, final int y, final int z) { - final Int3 i = new Int3(); - - i.x = x; - i.y = y; - i.z = z; - - return i; - } - - @Override - public boolean equals(final Object b) { - final 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/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index a5eeecc9..1461e1bc 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -27,7 +27,7 @@ import paulscode.sound.SoundSystemConfig; public class SoundPhysics { - // Private fields + private static final String logPrefix = "[SOUND PHYSICS]"; private static int auxFXSlot0; private static int auxFXSlot1; @@ -48,7 +48,6 @@ public class SoundPhysics { private static SoundCategory lastSoundCategory; private static String lastSoundName; - // Public fields public static int attenuationModel = SoundSystemConfig.ATTENUATION_ROLLOFF; public static float globalRolloffFactor = SoundPhysicsCore.Config.rolloffFactor; public static float globalVolumeMultiplier = 4.0f; @@ -67,58 +66,12 @@ public static void applyConfigChanges() { 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 + // 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); } } @@ -153,38 +106,17 @@ private static void setupEFX() { 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 @@ -268,8 +200,8 @@ public static double calculateEntitySoundOffset(final Entity entity, final Sound // return 0.0; } - private static float getBlockReflectivity(final Int3 blockPos) { - final Block block = mc.world.getBlockState(new BlockPos(blockPos.x, blockPos.y, blockPos.z)).getBlock(); + private static float getBlockReflectivity(final BlockPos blockPos) { + final Block block = mc.world.getBlockState(blockPos).getBlock(); final SoundType soundType = block.getSoundType(); float reflectivity = 0.5f; @@ -565,8 +497,7 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi final double rayLength = soundPos.distanceTo(rayHit.hitVec); // Additional bounces - Int3 lastHitBlock = Int3.create(rayHit.getBlockPos().getX(), rayHit.getBlockPos().getY(), - rayHit.getBlockPos().getZ()); + BlockPos lastHitBlock = rayHit.getBlockPos(); Vec3d lastHitPos = rayHit.hitVec; Vec3d lastHitNormal = getNormalFromFacing(rayHit.sideHit); Vec3d lastRayDir = rayDir; @@ -615,8 +546,7 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi lastHitPos = newRayHit.hitVec; lastHitNormal = getNormalFromFacing(newRayHit.sideHit); lastRayDir = newRayDir; - lastHitBlock = Int3.create(newRayHit.getBlockPos().getX(), newRayHit.getBlockPos().getY(), - newRayHit.getBlockPos().getZ()); + lastHitBlock = newRayHit.getBlockPos(); // Cast one final ray towards the player. If it's // unobstructed, then the sound source and the player From 6c7fc30f6e45551622ff2aa49975f5bc41ac161a Mon Sep 17 00:00:00 2001 From: daipenger Date: Thu, 6 Apr 2017 15:34:05 +0200 Subject: [PATCH 12/39] Link Opcodes again, further clean up --- .../sonicether/soundphysics/ReverbParams.java | 4 +- .../sonicether/soundphysics/SoundPhysics.java | 35 +-- .../soundphysics/SoundPhysicsCore.java | 228 ++++++++++-------- 3 files changed, 144 insertions(+), 123 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/ReverbParams.java b/src/main/java/com/sonicether/soundphysics/ReverbParams.java index cf650d59..b255a923 100644 --- a/src/main/java/com/sonicether/soundphysics/ReverbParams.java +++ b/src/main/java/com/sonicether/soundphysics/ReverbParams.java @@ -1,6 +1,7 @@ package com.sonicether.soundphysics; 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 @@ -86,7 +87,4 @@ public static ReverbParams getReverb3() { return r; } - ReverbParams() { - - } } diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 1461e1bc..2df9cd57 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -12,10 +12,6 @@ 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; @@ -54,6 +50,9 @@ public class SoundPhysics { public static float globalReverbMultiplier = 0.7f * SoundPhysicsCore.Config.globalReverbGain; public static double soundDistanceAllowance = SoundPhysicsCore.Config.soundDistanceAllowance; + /** + * CALLED BY ASM! + */ public static void init() { log("Initializing Sound Physics..."); setupEFX(); @@ -152,16 +151,25 @@ private static void setupEFX() { // effectslot } + /** + * CALLED BY ASM! + */ public static void setLastSoundCategory(final SoundCategory sc) { // log("Set last sound category"); lastSoundCategory = sc; } + /** + * CALLED BY ASM! + */ public static void setLastSoundName(final String name) { // log("Set last sound name: " + name); lastSoundName = name; } + /** + * CALLED BY ASM! + */ public static void onPlaySound(final float posX, final float posY, final float posZ, final int sourceID) { // log("On play sound"); logGeneral("On play sound... Sounrce ID: " + sourceID + " " + posX + ", " + posY + ", " + posZ @@ -191,13 +199,10 @@ public static void onPlaySound(final float posX, final float posY, final float p } public static double calculateEntitySoundOffset(final Entity entity, final SoundEvent sound) { - if (!sound.getSoundName().getResourcePath().matches(".*step.*")) { - // log("Offset entity say sound by " + entity.getEyeHeight()); - return entity.getEyeHeight(); - } else { - return 0.0; - } - // return 0.0; + if (sound.getSoundName().getResourcePath().matches(".*step.*")) + return 0; + + return entity.getEyeHeight(); } private static float getBlockReflectivity(final BlockPos blockPos) { @@ -905,12 +910,10 @@ protected static boolean checkErrorLog(final String errorMessage) { // sufficiently quiet to not play it. public static boolean shouldSoundPacketBeSent(final double posX, final double posY, final double posZ, final double volume) { - if (mc.player != null) { - final double distance = getDistanceFromPlayer(posX, posY, posZ); - return distance < 32.0; - } else { + if (mc.player == null) return false; - } + + return getDistanceFromPlayer(posX, posY, posZ) < 32; } private static double getDistanceFromPlayer(final double posX, final double posY, final double posZ) { diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java index 6ef345f4..c228f125 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java @@ -4,6 +4,7 @@ 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; @@ -31,6 +32,7 @@ @Mod(modid = SoundPhysicsCore.modid, version = SoundPhysicsCore.version, guiFactory = "com.sonicether.soundphysics.SPGUIFactory") public class SoundPhysicsCore implements IClassTransformer { + public static Configuration configFile; public static final String modid = "soundphysics"; @@ -173,124 +175,142 @@ private void log(final String message) { 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(final String paramString1, final String paramString2, byte[] paramArrayOfByte) { - InsnList localInsnList1 = new InsnList(); - localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "init", "()V")); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, + public byte[] transform(final String obfuscated, final String deobfuscated, byte[] bytes) { + InsnList toInject = new InsnList(); + InsnList helperList2 = new InsnList(); + + // SoundPhysics.init() in SoundManager.SoundSystemStarterThread + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "init", "()V", + false)); + bytes = patchMethodInClass(obfuscated, bytes, new String[] { "net.minecraft.client.audio.SoundManager$SoundSystemStarterThread", "ccq$a" }, new String[] { "", "" }, - new String[] { "(Lnet/minecraft/client/audio/SoundManager;)V", "(Lccq;)V" }, 183, 5, - new String[] { "", "" }, null, new InsnList[] { localInsnList1, localInsnList1 }, false, 0, - 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new VarInsnNode(25, 7)); - localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundCategory", - "(Lnet/minecraft/util/SoundCategory;)V")); - InsnList localInsnList2 = new InsnList(); - localInsnList2.add(new VarInsnNode(25, 7)); - localInsnList2.add( - new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundCategory", "(Lno;)V")); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, - new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, - new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 182, 5, - new String[] { "setVolume", "setVolume" }, null, new InsnList[] { localInsnList1, localInsnList2 }, - false, 0, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new VarInsnNode(25, 1)); - localInsnList1.add(new MethodInsnNode(185, "net/minecraft/client/audio/ISound", "getSoundLocation", - "()Lnet/minecraft/util/ResourceLocation;")); - localInsnList1.add( - new MethodInsnNode(182, "net/minecraft/util/ResourceLocation", "toString", "()Ljava/lang/String;")); - localInsnList1.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", - "(Ljava/lang/String;)V")); - localInsnList2 = new InsnList(); - localInsnList2.add(new VarInsnNode(25, 1)); - localInsnList2.add(new MethodInsnNode(185, "ccc", "a", "()Lkq;")); - localInsnList2.add(new MethodInsnNode(182, "kq", "toString", "()Ljava/lang/String;")); - localInsnList2.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", - "(Ljava/lang/String;)V")); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, - new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, - new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 182, 5, - new String[] { "setVolume", "setVolume" }, null, new InsnList[] { localInsnList1, localInsnList2 }, + new String[] { "(Lnet/minecraft/client/audio/SoundManager;)V", "(Lccq;)V" }, Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, new String[] { "", "" }, null, + new InsnList[] { toInject, toInject }, false, 0, 0, false, 0); + + // setLastSoundCategory(var6) in SoundManager.playSound() + 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", false)); + helperList2.add(new VarInsnNode(Opcodes.ALOAD, 7)); + helperList2.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", + "setLastSoundCategory", "(Lno;)V", false)); + bytes = patchMethodInClass(obfuscated, bytes, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, + new String[] { "playSound", "c" }, + new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, new String[] { "setVolume", "setVolume" }, null, + new InsnList[] { toInject, helperList2 }, false, 0, 0, false, 0); + + // setLastSoundName(name) in SoundManager.playSound() + 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;", true)); + toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "net/minecraft/util/ResourceLocation", "toString", + "()Ljava/lang/String;", false)); + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", + "setLastSoundName", "(Ljava/lang/String;)V", false)); + helperList2 = new InsnList(); + helperList2.add(new VarInsnNode(25, 1)); + helperList2.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "ccc", "a", "()Lkq;", true)); + helperList2.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "kq", "toString", "()Ljava/lang/String;", false)); + helperList2.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", + "setLastSoundName", "(Ljava/lang/String;)V", false)); + bytes = patchMethodInClass(obfuscated, bytes, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, + new String[] { "playSound", "c" }, + new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, new String[] { "setVolume", "setVolume" }, null, + new InsnList[] { toInject, helperList2 }, false, 0, 0, false, 0); + + // Global volume multiplier + toInject = new InsnList(); + toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", + "globalVolumeMultiplier", "F")); + toInject.add(new InsnNode(Opcodes.FMUL)); + bytes = patchMethodInClass(obfuscated, bytes, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, + new String[] { "playSound", "c" }, + new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, new String[] { "getClampedVolume", "e" }, + new String[] { "(Lnet/minecraft/client/audio/ISound;)F", "(Lccc;)F" }, new InsnList[] { toInject }, false, 0, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1 - .add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "globalVolumeMultiplier", "F")); - localInsnList1.add(new InsnNode(106)); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, - new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, new String[] { "playSound", "c" }, - new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, 183, 5, - new String[] { "getClampedVolume", "e" }, - new String[] { "(Lnet/minecraft/client/audio/ISound;)F", "(Lccc;)F" }, - new InsnList[] { localInsnList1 }, false, 0, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new VarInsnNode(25, 0)); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", + + // onPlaySound(var6) in paulscode.libraries.SourceLWJGLOpenAL.play() + toInject = new InsnList(); + toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); + toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", "Lpaulscode/sound/Vector3D;")); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "x", "F")); - localInsnList1.add(new VarInsnNode(25, 0)); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", + 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;")); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "y", "F")); - localInsnList1.add(new VarInsnNode(25, 0)); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "position", + 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;")); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/Vector3D", "z", "F")); - localInsnList1.add(new VarInsnNode(25, 0)); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/SourceLWJGLOpenAL", "channelOpenAL", + 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;")); - localInsnList1.add(new FieldInsnNode(180, "paulscode/sound/libraries/ChannelLWJGLOpenAL", "ALSource", + toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "paulscode/sound/libraries/ChannelLWJGLOpenAL", "ALSource", "Ljava/nio/IntBuffer;")); - localInsnList1.add(new InsnNode(3)); - localInsnList1.add(new MethodInsnNode(182, "java/nio/IntBuffer", "get", "(I)I", false)); - localInsnList1.add( - new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "onPlaySound", "(FFFI)V", false)); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, - new String[] { "paulscode.sound.libraries.SourceLWJGLOpenAL" }, new String[] { "play" }, - new String[] { "(Lpaulscode/sound/Channel;)V" }, 182, 5, new String[] { "play" }, null, - new InsnList[] { localInsnList1 }, false, 0, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "attenuationModel", "I")); - localInsnList1 - .add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "globalRolloffFactor", "F")); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, - new String[] { "paulscode.sound.SoundSystem" }, new String[] { "newSource" }, - new String[] { "(ZLjava/lang/String;Ljava/net/URL;Ljava/lang/String;ZFFFIF)V" }, 183, 5, - new String[] { "" }, null, new InsnList[] { localInsnList1 }, true, 2, 0, false, 0); - localInsnList1 = new InsnList(); - localInsnList1 - .add(new FieldInsnNode(178, "com/sonicether/soundphysics/SoundPhysics", "soundDistanceAllowance", "D")); - localInsnList1.add(new InsnNode(107)); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, + 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)); + bytes = patchMethodInClass(obfuscated, bytes, new String[] { "paulscode.sound.libraries.SourceLWJGLOpenAL" }, + new String[] { "play" }, new String[] { "(Lpaulscode/sound/Channel;)V" }, Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, new String[] { "play" }, null, new InsnList[] { toInject }, false, 0, 0, + false, 0); + + // attenuation model and rolloff factor + 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")); + bytes = patchMethodInClass(obfuscated, bytes, new String[] { "paulscode.sound.SoundSystem" }, + new String[] { "newSource" }, + new String[] { "(ZLjava/lang/String;Ljava/net/URL;Ljava/lang/String;ZFFFIF)V" }, Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, new String[] { "" }, null, new InsnList[] { toInject }, true, 2, 0, + false, 0); + + // Multiply sound distance volume play decision by + // SoundPhysics.soundDistanceAllowance + toInject = new InsnList(); + toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", + "soundDistanceAllowance", "D")); + toInject.add(new InsnNode(Opcodes.DMUL)); + bytes = patchMethodInClass(obfuscated, bytes, new String[] { "net.minecraft.server.management.PlayerList", "mt" }, new String[] { "sendToAllNearExcept", "a" }, new String[] { "(Lnet/minecraft/entity/player/EntityPlayer;DDDDILnet/minecraft/network/Packet;)V", "(Laay;DDDDILfm;)V" }, - 152, 0, new String[] { "", "" }, new String[] { "", "" }, new InsnList[] { localInsnList1 }, true, 0, 0, - false, 0); - localInsnList1 = new InsnList(); - localInsnList1.add(new VarInsnNode(25, 1)); - localInsnList1 - .add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", "calculateEntitySoundOffset", - "(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/SoundEvent;)D", false)); - localInsnList1.add(new InsnNode(99)); - localInsnList1.add(new VarInsnNode(25, 0)); - localInsnList2 = new InsnList(); - localInsnList2.add(new VarInsnNode(25, 1)); - localInsnList2.add(new MethodInsnNode(184, "com/sonicether/soundphysics/SoundPhysics", + Opcodes.DCMPG, AbstractInsnNode.INSN, new String[] { "", "" }, new String[] { "", "" }, + new InsnList[] { toInject }, true, 0, 0, false, 0); + + // Offset entity sound by their eye height + 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)); + helperList2 = new InsnList(); + helperList2.add(new VarInsnNode(Opcodes.ALOAD, 1)); + helperList2.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "calculateEntitySoundOffset", "(Lsn;Lnm;)D", false)); - localInsnList2.add(new InsnNode(99)); - localInsnList2.add(new VarInsnNode(25, 0)); - paramArrayOfByte = patchMethodInClass(paramString1, paramArrayOfByte, - new String[] { "net.minecraft.entity.Entity", "sn" }, new String[] { "playSound", "a" }, - new String[] { "(Lnet/minecraft/util/SoundEvent;FF)V", "(Lnm;FF)V" }, 182, 5, - new String[] { "getSoundCategory", "bC" }, null, new InsnList[] { localInsnList1, localInsnList2 }, - true, 0, 0, false, -3); - return paramArrayOfByte; + helperList2.add(new InsnNode(Opcodes.DADD)); + helperList2.add(new VarInsnNode(Opcodes.ALOAD, 0)); + bytes = patchMethodInClass(obfuscated, bytes, new String[] { "net.minecraft.entity.Entity", "sn" }, + new String[] { "playSound", "a" }, new String[] { "(Lnet/minecraft/util/SoundEvent;FF)V", "(Lnm;FF)V" }, + Opcodes.INVOKEVIRTUAL, AbstractInsnNode.METHOD_INSN, new String[] { "getSoundCategory", "bC" }, null, + new InsnList[] { toInject, helperList2 }, true, 0, 0, false, -3); + + return bytes; } /** From 5697cba976bae29a3af02c872ed0848fdf3c92b7 Mon Sep 17 00:00:00 2001 From: daipenger Date: Thu, 6 Apr 2017 15:57:30 +0200 Subject: [PATCH 13/39] Further clean up --- .../soundphysics/SPFMLLoadingPlugin.java | 19 +- .../sonicether/soundphysics/SPGUIFactory.java | 7 +- .../sonicether/soundphysics/SoundPhysics.java | 234 +++++------------- .../soundphysics/SoundPhysicsCore.java | 26 +- 4 files changed, 72 insertions(+), 214 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java b/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java index e9d73473..ab9898b2 100644 --- a/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java +++ b/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java @@ -2,12 +2,11 @@ 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.2") -public class SPFMLLoadingPlugin implements IFMLLoadingPlugin, IFMLCallHook { +public class SPFMLLoadingPlugin implements IFMLLoadingPlugin { @Override public String[] getASMTransformerClass() { @@ -16,34 +15,20 @@ public String[] getASMTransformerClass() { @Override public String getModContainerClass() { - // return SPDummyContainer.class.getName(); return null; } @Override public String getSetupClass() { - return this.getClass().getName(); + return null; } @Override public void injectData(final 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 index 8788baa9..c12751f1 100644 --- a/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java +++ b/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java @@ -10,8 +10,6 @@ public class SPGUIFactory implements IModGuiFactory { @Override public void initialize(final Minecraft minecraftInstance) { - // TODO Auto-generated method stub - } @Override @@ -21,13 +19,12 @@ public Class mainConfigGuiClass() { @Override public Set runtimeGuiCategories() { - // TODO Auto-generated method stub return null; } + @SuppressWarnings("deprecation") @Override - public RuntimeOptionGuiHandler getHandlerFor(final RuntimeOptionCategoryElement element) { - // TODO Auto-generated method stub + public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { return null; } diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 2df9cd57..337456e7 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -19,7 +19,6 @@ 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 paulscode.sound.SoundSystemConfig; public class SoundPhysics { @@ -44,6 +43,8 @@ public class SoundPhysics { private static SoundCategory lastSoundCategory; private static String lastSoundName; + // 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 globalVolumeMultiplier = 4.0f; @@ -51,7 +52,7 @@ public class SoundPhysics { public static double soundDistanceAllowance = SoundPhysicsCore.Config.soundDistanceAllowance; /** - * CALLED BY ASM! + * CALLED BY ASM INJECTED CODE! */ public static void init() { log("Initializing Sound Physics..."); @@ -136,39 +137,24 @@ private static void setupEFX() { 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 } /** - * CALLED BY ASM! + * CALLED BY ASM INJECTED CODE! */ public static void setLastSoundCategory(final SoundCategory sc) { - // log("Set last sound category"); lastSoundCategory = sc; } /** - * CALLED BY ASM! + * CALLED BY ASM INJECTED CODE! */ public static void setLastSoundName(final String name) { - // log("Set last sound name: " + name); lastSoundName = name; } /** - * CALLED BY ASM! + * CALLED BY ASM INJECTED CODE! */ public static void onPlaySound(final float posX, final float posY, final float posZ, final int sourceID) { // log("On play sound"); @@ -198,6 +184,9 @@ public static void onPlaySound(final float posX, final float posY, final float p // System.out.println(soundCategory.getCategoryName()); } + /** + * CALLED BY ASM INJECTED CODE! + */ public static double calculateEntitySoundOffset(final Entity entity, final SoundEvent sound) { if (sound.getSoundName().getResourcePath().matches(".*step.*")) return 0; @@ -205,6 +194,7 @@ public static double calculateEntitySoundOffset(final Entity entity, final Sound return entity.getEyeHeight(); } + @SuppressWarnings("deprecation") private static float getBlockReflectivity(final BlockPos blockPos) { final Block block = mc.world.getBlockState(blockPos).getBlock(); final SoundType soundType = block.getSoundType(); @@ -241,23 +231,7 @@ private static float getBlockReflectivity(final BlockPos blockPos) { } private static Vec3d getNormalFromFacing(final 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; - - final Vec3i inormal = sideHit.getDirectionVec(); - - normal = new Vec3d(inormal.getX(), inormal.getY(), inormal.getZ()); - - return normal; + return new Vec3d(sideHit.getDirectionVec()); } private static Vec3d reflect(final Vec3d dir, final Vec3d normal) { @@ -310,6 +284,7 @@ private static Vec3d offsetSoundByName(Vec3d soundPos, final Vec3d playerPos, fi return soundPos; } + @SuppressWarnings("deprecation") private static void evaluateEnvironment(final int sourceID, final float posX, final float posY, final float posZ) { if (posX < 0.01f && posY < 0.01f && posZ < 0.01f) { // logDetailed("Menu sound!"); @@ -702,38 +677,6 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi 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); } @@ -771,70 +714,37 @@ private static void setEnvironment(final int sourceID, final float sendGain0, fi * effect. */ protected static void setReverbParams(final ReverbParams r, final int auxFXSlot, final 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 + 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 @@ -846,27 +756,18 @@ protected static void log(final String message) { } protected static void logOcclusion(final String message) { - if (!SoundPhysicsCore.Config.occlusionLogging) { - return; - } - - System.out.println(logPrefix + " [OCCLUSION] " + ": " + message); + if (SoundPhysicsCore.Config.occlusionLogging) + System.out.println(logPrefix + " [OCCLUSION] " + ": " + message); } protected static void logEnvironment(final String message) { - if (!SoundPhysicsCore.Config.environmentLogging) { - return; - } - - System.out.println(logPrefix + " [ENVIRONMENT] " + ": " + message); + if (SoundPhysicsCore.Config.environmentLogging) + System.out.println(logPrefix + " [ENVIRONMENT] " + ": " + message); } protected static void logGeneral(final String message) { - if (!SoundPhysicsCore.Config.debugLogging) { - return; - } - - System.out.println(logPrefix + ": " + message); + if (SoundPhysicsCore.Config.debugLogging) + System.out.println(logPrefix + ": " + message); } protected static void logError(final String errorMessage) { @@ -875,35 +776,34 @@ protected static void logError(final String errorMessage) { protected static boolean checkErrorLog(final String errorMessage) { final int error = AL10.alGetError(); - String errorName; + if (error == 0) + return false; - 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; - } + String errorName; - System.out.println(logPrefix + " [ERROR]: " + errorMessage + " OpenAL error " + errorName); - return true; - } else { - return false; + 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; } // TODO: Find fancy way of determining if a sound is going to be @@ -921,10 +821,6 @@ private static double getDistanceFromPlayer(final double posX, final double posY double y = mc.player.posY - posY; double z = mc.player.posZ - posZ; - x *= x; - y *= y; - z *= z; - - return Math.sqrt(x + y + z); + return Math.sqrt(x * x + y * y + z * z); } } diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java index c228f125..a10ba0c5 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java @@ -168,11 +168,8 @@ public static void syncConfig() { } private void log(final String message) { - if (!Config.debugLogging) { - return; - } - - System.out.println(message); + if (Config.debugLogging) + System.out.println(message); } @Override @@ -214,7 +211,7 @@ public byte[] transform(final String obfuscated, final String deobfuscated, byte toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", "(Ljava/lang/String;)V", false)); helperList2 = new InsnList(); - helperList2.add(new VarInsnNode(25, 1)); + helperList2.add(new VarInsnNode(Opcodes.ALOAD, 1)); helperList2.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "ccc", "a", "()Lkq;", true)); helperList2.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "kq", "toString", "()Ljava/lang/String;", false)); helperList2.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", @@ -313,23 +310,6 @@ public byte[] transform(final String obfuscated, final String deobfuscated, byte return bytes; } - /** - * - * @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(final String currentClassName, final byte[] bytes, final String[] targetClassNames, final String[] targetMethodNames, final String[] targetMethodSignatures, final int targetNodeOpcode, final int targetNodeType, final String[] targetInvocationMethodNames, From c43f1d32efc52c15ddf1eb16a5fd54f6111584c6 Mon Sep 17 00:00:00 2001 From: daipenger Date: Thu, 6 Apr 2017 16:56:12 +0200 Subject: [PATCH 14/39] Remove yet another set of unneeded methods --- .../sonicether/soundphysics/SoundPhysics.java | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 337456e7..fb61ad91 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -806,21 +806,4 @@ protected static boolean checkErrorLog(final String errorMessage) { return true; } - // TODO: Find fancy way of determining if a sound is going to be - // sufficiently quiet to not play it. - public static boolean shouldSoundPacketBeSent(final double posX, final double posY, final double posZ, - final double volume) { - if (mc.player == null) - return false; - - return getDistanceFromPlayer(posX, posY, posZ) < 32; - } - - private static double getDistanceFromPlayer(final double posX, final double posY, final double posZ) { - double x = mc.player.posX - posX; - double y = mc.player.posY - posY; - double z = mc.player.posZ - posZ; - - return Math.sqrt(x * x + y * y + z * z); - } } From 7e65ae16bea0cfdcc442339464c7c3c42ee22051 Mon Sep 17 00:00:00 2001 From: daipenger Date: Fri, 7 Apr 2017 16:24:21 +0200 Subject: [PATCH 15/39] A lot of cleanup of the main algorithm Needs some rethinking (especially the direct line of sight affects sound too much and is buggy in its current state) --- .../sonicether/soundphysics/SoundPhysics.java | 264 +++++------------- 1 file changed, 69 insertions(+), 195 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index fb61ad91..422a68b4 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -157,15 +157,9 @@ public static void setLastSoundName(final String name) { * CALLED BY ASM INJECTED CODE! */ public static void onPlaySound(final float posX, final float posY, final float posZ, final int sourceID) { - // log("On play sound"); - logGeneral("On play sound... Sounrce ID: " + sourceID + " " + posX + ", " + posY + ", " + posZ + logGeneral("onPlaySound, Source 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; @@ -180,8 +174,6 @@ public static void onPlaySound(final float posX, final float posY, final float p log("Total calculation time for sound " + lastSoundName + ": " + (double) (endTime - startTime) / (double) 1000000 + " milliseconds"); } - - // System.out.println(soundCategory.getCategoryName()); } /** @@ -245,63 +237,59 @@ private static Vec3d reflect(final Vec3d dir, final Vec3d normal) { return new Vec3d(x, y, z); } - private static Vec3d offsetSoundByName(Vec3d soundPos, final Vec3d playerPos, final String name, - final String soundCategory) { + private static Vec3d offsetSoundByName(double soundX, double soundY, 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; - final Vec3d toPlayerVector = playerPos.subtract(soundPos).normalize(); + double tempNormX = 0; + double tempNormY = 0; + double tempNormZ = 0; - // names - if (name.matches(".*step.*")) { + if (soundY % 1.0 < 0.001 || name.matches(".*step.*")) { offsetY = 0.1; } - // categories - if (soundCategory.matches("block") || soundCategory.matches("record")) { - offsetTowardsPlayer = 0.89; + if (category == SoundCategory.BLOCKS || category == SoundCategory.RECORDS || name.matches(".*block.*")) { + // 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.xCoord - soundX; + tempNormY = playerPos.yCoord - soundY; + tempNormZ = playerPos.zCoord - soundZ; + 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; } - if (soundPos.yCoord % 1.0 < 0.001 && soundPos.yCoord > 0.01) { - offsetY = 0.1; - } - - 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); } @SuppressWarnings("deprecation") private static void evaluateEnvironment(final int sourceID, final float posX, final float posY, final float posZ) { if (posX < 0.01f && posY < 0.01f && posZ < 0.01f) { - // logDetailed("Menu sound!"); - + // Supposed to catch menu sounds, but quite crude 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.player == null) { + if (mc.player == null || mc.world == null) { return; } - if (mc.world == null) { - return; - } + final boolean isRain = lastSoundName.matches(".*rain.*"); - if (SoundPhysicsCore.Config.skipRainOcclusionTracing && lastSoundName.matches(".*rain.*")) { + if (SoundPhysicsCore.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; } @@ -309,96 +297,44 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi float directCutoff = 1.0f; final float absorptionCoeff = SoundPhysicsCore.Config.globalBlockAbsorption * 3.0f; - // Direct sound occlusion - Vec3d soundPos = new Vec3d(posX, posY, posZ); - Vec3d playerPos = mc.player.getPositionVector(); - playerPos = new Vec3d(playerPos.xCoord, playerPos.yCoord + mc.player.getEyeHeight(), playerPos.zCoord); - - soundPos = offsetSoundByName(soundPos, playerPos, lastSoundName, lastSoundCategory.getName()); - - // Vec3d toPlayerVector = soundPos.subtract(playerPos).normalize(); - final Vec3d toPlayerVector = playerPos.subtract(soundPos).normalize(); + 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(); 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)); - } + + " To player vector: " + normalToPlayer.xCoord + ", " + normalToPlayer.yCoord + ", " + + normalToPlayer.zCoord); - boolean thisHitSolid = false; // TODO: This will be true if the sound - // doesn't come from inside a block! + Vec3d rayOrigin = soundPos; float occlusionAccumulation = 0.0f; for (int i = 0; i < 10; i++) { final RayTraceResult rayHit = mc.world.rayTraceBlocks(rayOrigin, playerPos, true); - // If we hit a block - if (rayHit != null) { - // Get the normal of the side hit - // Vec3d hitNormal = getNormalFromFacing(rayHit.sideHit); + if (rayHit == null) + break; + + final Block blockHit = mc.world.getBlockState(rayHit.getBlockPos()).getBlock(); - // 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); + float blockOcclusion = 1.0f; - // Block blockHit = mc.world.getBlock(rayHit.blockX, - // rayHit.blockY, rayHit.blockZ); - final Block blockHit = mc.world.getBlockState(rayHit.getBlockPos()).getBlock(); + if (!blockHit.isOpaqueCube(blockHit.getDefaultState())) { + // log("not a solid block!"); + blockOcclusion *= 0.15f; + } - float blockOcclusion = 1.0f; + logOcclusion(blockHit.getUnlocalizedName() + " " + rayHit.hitVec.xCoord + ", " + rayHit.hitVec.yCoord + + ", " + rayHit.hitVec.zCoord); - if (!blockHit.isOpaqueCube(blockHit.getDefaultState())) { - // log("not a solid block!"); - blockOcclusion *= 0.15f; - } + occlusionAccumulation += blockOcclusion; - 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; - } else { - // System.out.println("Didn't hit anything!"); - break; - } + rayOrigin = new Vec3d(rayHit.hitVec.xCoord + normalToPlayer.xCoord * 0.1, + rayHit.hitVec.yCoord + normalToPlayer.yCoord * 0.1, + rayHit.hitVec.zCoord + normalToPlayer.zCoord * 0.1); + logOcclusion("New trace position: " + rayOrigin.xCoord + ", " + rayOrigin.yCoord + ", " + rayOrigin.zCoord); } directCutoff = (float) Math.exp(-occlusionAccumulation * absorptionCoeff); @@ -421,7 +357,7 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi directCutoff *= 1.0f - SoundPhysicsCore.Config.underwaterFilter; } - if (lastSoundName.matches(".*rain.*")) { + if (isRain) { setEnvironment(sourceID, sendGain0, sendGain1, sendGain2, sendGain3, sendCutoff0, sendCutoff1, sendCutoff2, sendCutoff3, directCutoff, directGain); return; @@ -435,21 +371,17 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi final int numRays = SoundPhysicsCore.Config.environmentEvaluationRays; final int rayBounces = 4; - final int[] rayHits = new int[rayBounces]; - final float[] bounceReflectivityRatio = new float[rayBounces]; float sharedAirspace = 0.0f; final float rcpTotalRays = 1.0f / (numRays * rayBounces); - final float rcpPrimaryRays = 1.0f / (numRays); - - final double reflectionEnergyCurve = 1.0; + 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 * 1.0f; + final float longitude = gAngle * fi; final float latitude = (float) Math.asin(fiN * 2.0f - 1.0f); Vec3d rayDir = new Vec3d(0.0, 0.0, 0.0); @@ -495,31 +427,18 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi newRayStart.yCoord + newRayDir.yCoord * maxDistance, newRayStart.zCoord + newRayDir.zCoord * maxDistance); - // log("New ray dir: " + newRayDir.xCoord + ", " + - // newRayDir.yCoord + ", " + newRayDir.zCoord); - final RayTraceResult newRayHit = mc.world.rayTraceBlocks(newRayStart, newRayEnd, true); - // float energyTowardsPlayer = - // (float)Math.pow(MathHelper.clamp_float(soundDirToPlayerDot, - // 0.0f, 1.0f), 1.0f); float energyTowardsPlayer = 0.25f; final float blockReflectivity = getBlockReflectivity(lastHitBlock); energyTowardsPlayer *= blockReflectivity * 0.75f + 0.25f; - final float bounceToPlayerDistance = (float) lastHitPos.distanceTo(playerPos); - // energyTowardsPlayer *= 1.0f / - // ((float)Math.pow(bounceToPlayerDistance, 2.0) + 0.01f); - - 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; - } + if (newRayHit == null) { + totalRayDistance += lastHitPos.distanceTo(playerPos); + } else { final double newRayLength = lastHitPos.distanceTo(newRayHit.hitVec); - rayHits[j]++; - bounceReflectivityRatio[j] += (float) Math.pow(blockReflectivity, reflectionEnergyCurve); + + bounceReflectivityRatio[j] += (float) blockReflectivity; totalRayDistance += newRayLength; @@ -544,22 +463,16 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi sharedAirspace += 1.0f; } } - } else { - totalRayDistance += lastHitPos.distanceTo(playerPos); } - final float reflectionDelay = (float) Math.pow(Math.max(totalRayDistance, 0.0), 1.0) * 0.12f - * blockReflectivity; + 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); - // float cross3 = 1.0f - - // MathHelper.clamp_float(Math.abs(reflectionDelay - 3.0f), - // 0.0f, 1.0f); final float cross3 = MathHelper.clamp(reflectionDelay - 2.0f, 0.0f, 1.0f); - /* 1.0 / numRays */ sendGain0 += cross0 * energyTowardsPlayer * 6.4f * rcpTotalRays; + sendGain0 += cross0 * energyTowardsPlayer * 6.4f * rcpTotalRays; sendGain1 += cross1 * energyTowardsPlayer * 12.8f * rcpTotalRays; sendGain2 += cross2 * energyTowardsPlayer * 12.8f * rcpTotalRays; sendGain3 += cross3 * energyTowardsPlayer * 12.8f * rcpTotalRays; @@ -569,28 +482,16 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi break; } } - - // log("Hit " + mc.world.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"); } } // log("total reflectivity ratio: " + totalReflectivityRatio); - bounceReflectivityRatio[0] = (float) Math.pow(bounceReflectivityRatio[0] / numRays, - 1.0 / reflectionEnergyCurve); - bounceReflectivityRatio[1] = (float) Math.pow(bounceReflectivityRatio[1] / numRays, - 1.0 / reflectionEnergyCurve); - bounceReflectivityRatio[2] = (float) Math.pow(bounceReflectivityRatio[2] / numRays, - 1.0 / reflectionEnergyCurve); - bounceReflectivityRatio[3] = (float) Math.pow(bounceReflectivityRatio[3] / numRays, - 1.0 / reflectionEnergyCurve); + bounceReflectivityRatio[0] = bounceReflectivityRatio[0] / numRays; + bounceReflectivityRatio[1] = bounceReflectivityRatio[1] / numRays; + bounceReflectivityRatio[2] = bounceReflectivityRatio[2] / numRays; + bounceReflectivityRatio[3] = bounceReflectivityRatio[3] / numRays; sharedAirspace *= 64.0f; @@ -622,33 +523,16 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi 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; + sendGain1 *= (float) bounceReflectivityRatio[1]; 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(sendGain0 * 1.00f - 0.00f, 0.0f, 1.0f); - sendGain1 = MathHelper.clamp(sendGain1 * 1.00f - 0.00f, 0.0f, 1.0f); + 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); @@ -660,16 +544,6 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi 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.player.isInWater()) { sendCutoff0 *= 0.4f; sendCutoff1 *= 0.4f; From 89c7d1da70483466563d64cc55f692a3f21e6f58 Mon Sep 17 00:00:00 2001 From: daipenger Date: Fri, 7 Apr 2017 16:26:19 +0200 Subject: [PATCH 16/39] Version 1.0.1, mcmod.info cleaned up --- .../com/sonicether/soundphysics/SoundPhysicsCore.java | 2 +- src/main/resources/mcmod.info | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java index a10ba0c5..f508c84a 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java @@ -36,7 +36,7 @@ public class SoundPhysicsCore implements IClassTransformer { public static Configuration configFile; public static final String modid = "soundphysics"; - public static final String version = "1.0.0"; + public static final String version = "1.0.1"; // Config variables public static class Config { diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 33caeb5b..93af47d9 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", + "version": "1.0.1", "mcversion": "1.11.2", "url": "", - "updateUrl": "", - "authorList": ["Sonic Ether"], - //"credits": "", - "logoFile": "", - "screenshots": [], - "dependencies": [] + "authorList": ["Sonic Ether"] } ] From 6fb2a1ab05484b0bccc3f9551b35ebe3b5ae4c06 Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 12 Apr 2017 00:34:32 +0200 Subject: [PATCH 17/39] Complete refactoring --- build.gradle | 2 +- .../com/sonicether/soundphysics/Config.java | 150 ++++++ .../soundphysics/CoreModInjector.java | 253 ++++++++++ ...LLoadingPlugin.java => CoreModLoader.java} | 70 +-- .../sonicether/soundphysics/ReverbParams.java | 16 +- .../sonicether/soundphysics/SPConfigGUI.java | 44 -- .../sonicether/soundphysics/SPGuiConfig.java | 13 + .../sonicether/soundphysics/SoundPhysics.java | 180 ++++--- .../soundphysics/SoundPhysicsCore.java | 460 ------------------ src/main/resources/mcmod.info | 2 +- 10 files changed, 564 insertions(+), 626 deletions(-) create mode 100644 src/main/java/com/sonicether/soundphysics/Config.java create mode 100644 src/main/java/com/sonicether/soundphysics/CoreModInjector.java rename src/main/java/com/sonicether/soundphysics/{SPFMLLoadingPlugin.java => CoreModLoader.java} (78%) delete mode 100644 src/main/java/com/sonicether/soundphysics/SPConfigGUI.java create mode 100644 src/main/java/com/sonicether/soundphysics/SPGuiConfig.java delete mode 100644 src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java diff --git a/build.gradle b/build.gradle index fd19fc68..c83f83f6 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ archivesBaseName = "Sound-Physics" jar { manifest { - attributes 'FMLCorePlugin': 'com.sonicether.soundphysics.SPFMLLoadingPlugin' + attributes 'FMLCorePlugin': 'com.sonicether.soundphysics.CoreModLoader' attributes 'FMLCorePluginContainsFMLMod': 'true' } } 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..3335a7c8 --- /dev/null +++ b/src/main/java/com/sonicether/soundphysics/Config.java @@ -0,0 +1,150 @@ +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 { + + private Configuration forgeConfig; + + // 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; + + private static final String categoryGeneral = "General"; + private static final String categoryPerformance = "Performance"; + private static final String categoryMaterialProperties = "Material properties"; + private static final String categoryMisc = "Misc"; + + 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))); + list.add(new ConfigElement(this.forgeConfig.getCategory(Config.categoryMisc))); + + 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, 1.0f, 0.0f, + 1.0f, "Sound reflectivity for stone blocks."); + woodReflectivity = this.forgeConfig.getFloat("Wood Reflectivity", categoryMaterialProperties, 0.4f, 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.5f, 0.0f, + 1.0f, "Sound reflectivity for foliage blocks (leaves, grass, etc.)."); + metalReflectivity = this.forgeConfig.getFloat("Metal Reflectivity", categoryMaterialProperties, 1.0f, 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.05f, 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."); + + // misc + debugLogging = this.forgeConfig.getBoolean("Debug Logging", categoryMisc, false, "General debug logging"); + occlusionLogging = this.forgeConfig.getBoolean("Occlusion Logging", categoryMisc, false, + "Occlusion tracing information logging"); + environmentLogging = this.forgeConfig.getBoolean("Environment Logging", categoryMisc, false, + "Environment evaluation information logging"); + performanceLogging = this.forgeConfig.getBoolean("Performance Logging", categoryMisc, false, + "Performance information logging"); + + 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..4713a10c --- /dev/null +++ b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java @@ -0,0 +1,253 @@ +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) { + InsnList toInject = new InsnList(); + + // SoundPhysics.init() in SoundManager.SoundSystemStarterThread + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "init", "()V", + false)); + + bytes = patchMethodInClass(obfuscated, bytes, "ccq$a", "", "(Lccq;)V", Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, "", null, toInject, false, 0, 0, false, 0); + + // setLastSoundCategory(var6) in SoundManager.playSound() + toInject = new InsnList(); + toInject.add(new VarInsnNode(Opcodes.ALOAD, 7)); + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", + "setLastSoundCategory", "(Lno;)V", false)); + + bytes = patchMethodInClass(obfuscated, bytes, "ccq", "c", "(Lccc;)V", Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, "setVolume", null, toInject, false, 0, 0, false, 0); + + // setLastSoundName(name) in SoundManager.playSound() + toInject = new InsnList(); + toInject.add(new VarInsnNode(Opcodes.ALOAD, 1)); + toInject.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "ccc", "a", "()Lkq;", true)); + toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "kq", "toString", "()Ljava/lang/String;", false)); + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", + "setLastSoundName", "(Ljava/lang/String;)V", false)); + + bytes = patchMethodInClass(obfuscated, bytes, "ccq", "c", "(Lccc;)V", Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, "setVolume", null, toInject, false, 0, 0, false, 0); + + // Global volume multiplier + toInject = new InsnList(); + toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", + "globalVolumeMultiplier", "F")); + toInject.add(new InsnNode(Opcodes.FMUL)); + + bytes = patchMethodInClass(obfuscated, bytes, "ccq", "c", "(Lccc;)V", Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, "e", "(Lccc;)F", toInject, false, 0, 0, false, 0); + + // onPlaySound(var6) in paulscode.libraries.SourceLWJGLOpenAL.play() + 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)); + + bytes = patchMethodInClass(obfuscated, bytes, "paulscode.sound.libraries.SourceLWJGLOpenAL", "play", + "(Lpaulscode/sound/Channel;)V", Opcodes.INVOKEVIRTUAL, AbstractInsnNode.METHOD_INSN, "play", null, + toInject, false, 0, 0, false, 0); + + // attenuation model and rolloff factor + 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")); + + bytes = patchMethodInClass(obfuscated, bytes, "paulscode.sound.SoundSystem", "newSource", + "(ZLjava/lang/String;Ljava/net/URL;Ljava/lang/String;ZFFFIF)V", Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, "", null, toInject, true, 2, 0, false, 0); + + // Multiply sound distance volume play decision by + // SoundPhysics.soundDistanceAllowance + toInject = new InsnList(); + toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", + "soundDistanceAllowance", "D")); + toInject.add(new InsnNode(Opcodes.DMUL)); + + bytes = patchMethodInClass(obfuscated, bytes, "mt", "a", "(Laay;DDDDILfm;)V", Opcodes.DCMPG, + AbstractInsnNode.INSN, "", "", toInject, true, 0, 0, false, 0); + + // Offset entity sound by their eye height + toInject = new InsnList(); + toInject.add(new VarInsnNode(Opcodes.ALOAD, 1)); + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", + "calculateEntitySoundOffset", "(Lsn;Lnm;)D", false)); + toInject.add(new InsnNode(Opcodes.DADD)); + toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); + + bytes = patchMethodInClass(obfuscated, bytes, "sn", "a", "(Lnm;FF)V", Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, "bC", null, toInject, true, 0, 0, false, -3); + + return bytes; + } + + private byte[] patchMethodInClass(final String obfuscatedClassName, final byte[] bytes, final String targetClass, + 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) { + + // If this is not the target class, leave! + if (!obfuscatedClassName.equals(targetClass)) { + return bytes; + } + + log("################################################################# Patching Class: " + targetClass); + + // Setup ASM class manipulation stuff + final ClassNode classNode = new ClassNode(); + final 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 + final Iterator methods = classNode.methods.iterator(); + while (methods.hasNext()) { + final MethodNode m = methods.next(); + log("********* Method Name: " + m.name + " Desc: " + m.desc); + + // Check if this is the method name and the signature matches + if (m.name.equals(targetMethod) && m.desc.equals(targetMethodSignature)) { + log("*************************************** Inside target method: " + targetMethod); + + AbstractInsnNode currentNode = null; + AbstractInsnNode targetNode = null; + + final ListIterator iter = m.instructions.iterator(); + + // Loop over the instruction set + while (iter.hasNext()) { + currentNode = iter.next(); + + if (currentNode.getOpcode() == targetNodeOpcode) { + + if (targetNodeType == AbstractInsnNode.METHOD_INSN) { + if (currentNode.getType() == AbstractInsnNode.METHOD_INSN) { + final 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; + } + + } + } + } else { + if (currentNode.getType() == targetNodeType) { + log("Found target node for injection: " + targetNodeOpcode); + targetNode = currentNode; + } + } + + // TODO: BREAK STATEMENTS! BUT MAY NOT WORK IF THERE ARE + // MORE THAN ONE MATCHING TARGET NODES! (offsets have to + // be corrected) + + } + } + + if (targetNode == null) { + 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 (targetNode == null) { + break; + } + + // If we've found the target, inject the instructions! + for (int i = 0; i < nodesToDeleteBefore; i++) { + final AbstractInsnNode previousNode = targetNode.getPrevious(); + log("Removing Node " + previousNode.getOpcode()); + m.instructions.remove(previousNode); + } + + for (int i = 0; i < nodesToDeleteAfter; i++) { + final 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; + } + } + + final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); + classNode.accept(writer); + return writer.toByteArray(); + } + + private void log(final String message) { + if (Config.debugLogging) { + System.out.println(message); + } + } + +} diff --git a/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java b/src/main/java/com/sonicether/soundphysics/CoreModLoader.java similarity index 78% rename from src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java rename to src/main/java/com/sonicether/soundphysics/CoreModLoader.java index ab9898b2..30b5d65d 100644 --- a/src/main/java/com/sonicether/soundphysics/SPFMLLoadingPlugin.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModLoader.java @@ -1,35 +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 = "1.11.2") -public class SPFMLLoadingPlugin implements IFMLLoadingPlugin { - - @Override - public String[] getASMTransformerClass() { - return new String[] { SoundPhysicsCore.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; - } - -} +package com.sonicether.soundphysics; + +import java.util.Map; + +import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; +import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.MCVersion; + +@MCVersion(value = "1.11.2") +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/ReverbParams.java b/src/main/java/com/sonicether/soundphysics/ReverbParams.java index b255a923..97f269f0 100644 --- a/src/main/java/com/sonicether/soundphysics/ReverbParams.java +++ b/src/main/java/com/sonicether/soundphysics/ReverbParams.java @@ -22,13 +22,13 @@ public static ReverbParams getReverb0() { 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; } @@ -40,13 +40,13 @@ public static ReverbParams getReverb1() { 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; } @@ -58,13 +58,13 @@ public static ReverbParams getReverb2() { 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; } @@ -76,13 +76,13 @@ public static ReverbParams getReverb3() { 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; } 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 63e2efd8..00000000 --- a/src/main/java/com/sonicether/soundphysics/SPConfigGUI.java +++ /dev/null @@ -1,44 +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.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(final GuiScreen parent) { - super(parent, getConfigElements(), SoundPhysicsCore.modid, false, false, "Sound Physics Configuration"); - } - - /** Compiles a list of config elements */ - private static List getConfigElements() { - final ArrayList list = new ArrayList(); - - // Add categories to config GUI - list.add(categoryElement(Configuration.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(final String category, final String name, final 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/SPGuiConfig.java b/src/main/java/com/sonicether/soundphysics/SPGuiConfig.java new file mode 100644 index 00000000..da53b926 --- /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, SoundPhysics.instance.config.getConfigElements(), SoundPhysics.modid, false, false, + "Sound Physics Configuration"); + } + +} \ No newline at end of file diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 422a68b4..caf13700 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -19,10 +19,36 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.Instance; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import paulscode.sound.SoundSystemConfig; +@Mod(modid = SoundPhysics.modid, version = SoundPhysics.version, guiFactory = "com.sonicether.soundphysics.SPGuiFactory") public class SoundPhysics { + public static final String modid = "soundphysics"; + public static final String version = "1.0.2"; + @Instance(modid) + public static SoundPhysics instance; + + public final Config config; + + public SoundPhysics() { + this.config = new Config(); + } + + @Mod.EventHandler + public void preInit(final FMLPreInitializationEvent event) { + this.config.preInit(event); + } + + @Mod.EventHandler + public void init(final FMLInitializationEvent event) { + this.config.init(event); + } + private static final String logPrefix = "[SOUND PHYSICS]"; private static int auxFXSlot0; private static int auxFXSlot1; @@ -46,10 +72,10 @@ public class SoundPhysics { // 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 float globalReverbMultiplier = 0.7f * Config.globalReverbGain; + public static double soundDistanceAllowance = Config.soundDistanceAllowance; /** * CALLED BY ASM INJECTED CODE! @@ -61,9 +87,9 @@ public static void init() { } public static void applyConfigChanges() { - globalRolloffFactor = SoundPhysicsCore.Config.rolloffFactor; - globalReverbMultiplier = 0.7f * SoundPhysicsCore.Config.globalReverbGain; - soundDistanceAllowance = SoundPhysicsCore.Config.soundDistanceAllowance; + 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 @@ -157,19 +183,21 @@ public static void setLastSoundName(final String name) { * CALLED BY ASM INJECTED CODE! */ public static void onPlaySound(final float posX, final float posY, final float posZ, final int sourceID) { - logGeneral("onPlaySound, Source ID: " + sourceID + " " + posX + ", " + posY + ", " + posZ - + " Sound category: " + lastSoundCategory.toString() + " Sound name: " + lastSoundName); + if (Config.debugLogging) { + logGeneral("onPlaySound, Source ID: " + sourceID + " " + posX + ", " + posY + ", " + posZ + + " Sound category: " + lastSoundCategory.toString() + " Sound name: " + lastSoundName); + } long startTime = 0; long endTime = 0; - if (SoundPhysicsCore.Config.performanceLogging) { + if (Config.performanceLogging) { startTime = System.nanoTime(); } evaluateEnvironment(sourceID, posX, posY, posZ); - if (SoundPhysicsCore.Config.performanceLogging) { + if (Config.performanceLogging) { endTime = System.nanoTime(); log("Total calculation time for sound " + lastSoundName + ": " + (double) (endTime - startTime) / (double) 1000000 + " milliseconds"); @@ -180,8 +208,9 @@ public static void onPlaySound(final float posX, final float posY, final float p * CALLED BY ASM INJECTED CODE! */ public static double calculateEntitySoundOffset(final Entity entity, final SoundEvent sound) { - if (sound.getSoundName().getResourcePath().matches(".*step.*")) + if (sound.getSoundName().getResourcePath().matches(".*step.*")) { return 0; + } return entity.getEyeHeight(); } @@ -194,30 +223,30 @@ private static float getBlockReflectivity(final BlockPos blockPos) { float reflectivity = 0.5f; if (soundType == SoundType.STONE) { - reflectivity = SoundPhysicsCore.Config.stoneReflectivity; + reflectivity = Config.stoneReflectivity; } else if (soundType == SoundType.WOOD) { - reflectivity = SoundPhysicsCore.Config.woodReflectivity; + reflectivity = Config.woodReflectivity; } else if (soundType == SoundType.GROUND) { - reflectivity = SoundPhysicsCore.Config.groundReflectivity; + reflectivity = Config.groundReflectivity; } else if (soundType == SoundType.PLANT) { - reflectivity = SoundPhysicsCore.Config.plantReflectivity; + reflectivity = Config.plantReflectivity; } else if (soundType == SoundType.METAL) { - reflectivity = SoundPhysicsCore.Config.metalReflectivity; + reflectivity = Config.metalReflectivity; } else if (soundType == SoundType.GLASS) { - reflectivity = SoundPhysicsCore.Config.glassReflectivity; + reflectivity = Config.glassReflectivity; } else if (soundType == SoundType.CLOTH) { - reflectivity = SoundPhysicsCore.Config.clothReflectivity; + reflectivity = Config.clothReflectivity; } else if (soundType == SoundType.SAND) { - reflectivity = SoundPhysicsCore.Config.sandReflectivity; + reflectivity = Config.sandReflectivity; } else if (soundType == SoundType.SNOW) { - reflectivity = SoundPhysicsCore.Config.snowReflectivity; + reflectivity = Config.snowReflectivity; } else if (soundType == SoundType.LADDER) { - reflectivity = SoundPhysicsCore.Config.woodReflectivity; + reflectivity = Config.woodReflectivity; } else if (soundType == SoundType.ANVIL) { - reflectivity = SoundPhysicsCore.Config.metalReflectivity; + reflectivity = Config.metalReflectivity; } - reflectivity *= SoundPhysicsCore.Config.globalBlockReflectance; + reflectivity *= Config.globalBlockReflectance; return reflectivity; } @@ -237,8 +266,8 @@ private static Vec3d reflect(final Vec3d dir, final Vec3d normal) { return new Vec3d(x, y, z); } - private static Vec3d offsetSoundByName(double soundX, double soundY, double soundZ, final Vec3d playerPos, - final String name, final SoundCategory category) { + 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; @@ -261,7 +290,7 @@ private static Vec3d offsetSoundByName(double soundX, double soundY, double soun tempNormX = playerPos.xCoord - soundX; tempNormY = playerPos.yCoord - soundY; tempNormZ = playerPos.zCoord - soundZ; - double length = Math.sqrt(tempNormX * tempNormX + tempNormY * tempNormY + tempNormZ * tempNormZ); + final double length = Math.sqrt(tempNormX * tempNormX + tempNormY * tempNormY + tempNormZ * tempNormZ); tempNormX /= length; tempNormY /= length; tempNormZ /= length; @@ -277,34 +306,32 @@ private static Vec3d offsetSoundByName(double soundX, double soundY, double soun @SuppressWarnings("deprecation") private static void evaluateEnvironment(final int sourceID, final float posX, final float posY, final float posZ) { - if (posX < 0.01f && posY < 0.01f && posZ < 0.01f) { - // Supposed to catch menu sounds, but quite crude + if (mc.player == null || mc.world == null || posY <= 0) { + // Menu clicks, 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.player == null || mc.world == null) { - return; - } - final boolean isRain = lastSoundName.matches(".*rain.*"); - if (SoundPhysicsCore.Config.skipRainOcclusionTracing && isRain) { + 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; - final float absorptionCoeff = SoundPhysicsCore.Config.globalBlockAbsorption * 3.0f; + 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(); - logGeneral("Player pos: " + playerPos.xCoord + ", " + playerPos.yCoord + ", " + playerPos.zCoord - + " Sound Pos: " + soundPos.xCoord + ", " + soundPos.yCoord + ", " + soundPos.zCoord - + " To player vector: " + normalToPlayer.xCoord + ", " + normalToPlayer.yCoord + ", " - + normalToPlayer.zCoord); + if (Config.debugLogging) { + logGeneral("Player pos: " + playerPos.xCoord + ", " + playerPos.yCoord + ", " + playerPos.zCoord + + " Sound Pos: " + soundPos.xCoord + ", " + soundPos.yCoord + ", " + soundPos.zCoord + + " To player vector: " + normalToPlayer.xCoord + ", " + normalToPlayer.yCoord + ", " + + normalToPlayer.zCoord); + } Vec3d rayOrigin = soundPos; @@ -313,8 +340,9 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi for (int i = 0; i < 10; i++) { final RayTraceResult rayHit = mc.world.rayTraceBlocks(rayOrigin, playerPos, true); - if (rayHit == null) + if (rayHit == null) { break; + } final Block blockHit = mc.world.getBlockState(rayHit.getBlockPos()).getBlock(); @@ -325,8 +353,10 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi blockOcclusion *= 0.15f; } - logOcclusion(blockHit.getUnlocalizedName() + " " + rayHit.hitVec.xCoord + ", " + rayHit.hitVec.yCoord - + ", " + rayHit.hitVec.zCoord); + if (Config.occlusionLogging) { + logOcclusion(blockHit.getUnlocalizedName() + " " + rayHit.hitVec.xCoord + ", " + rayHit.hitVec.yCoord + + ", " + rayHit.hitVec.zCoord); + } occlusionAccumulation += blockOcclusion; @@ -334,13 +364,18 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi rayHit.hitVec.yCoord + normalToPlayer.yCoord * 0.1, rayHit.hitVec.zCoord + normalToPlayer.zCoord * 0.1); - logOcclusion("New trace position: " + rayOrigin.xCoord + ", " + rayOrigin.yCoord + ", " + rayOrigin.zCoord); + if (Config.occlusionLogging) { + logOcclusion( + "New trace position: " + rayOrigin.xCoord + ", " + rayOrigin.yCoord + ", " + rayOrigin.zCoord); + } } directCutoff = (float) Math.exp(-occlusionAccumulation * absorptionCoeff); float directGain = (float) Math.pow(directCutoff, 0.1); - logOcclusion("direct cutoff: " + directCutoff + " direct gain:" + directGain); + if (Config.occlusionLogging) { + logOcclusion("direct cutoff: " + directCutoff + " direct gain:" + directGain); + } // Calculate reverb parameters for this sound float sendGain0 = 0.0f; @@ -354,7 +389,7 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi float sendCutoff3 = 1.0f; if (mc.player.isInsideOfMaterial(Material.WATER)) { - directCutoff *= 1.0f - SoundPhysicsCore.Config.underwaterFilter; + directCutoff *= 1.0f - Config.underwaterFilter; } if (isRain) { @@ -368,7 +403,7 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi 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; final float[] bounceReflectivityRatio = new float[rayBounces]; @@ -384,20 +419,9 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi final float longitude = gAngle * fi; final 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); - { - final double x = Math.cos(latitude) * Math.cos(longitude); - final double y = Math.cos(latitude) * Math.sin(longitude); - final double z = Math.sin(latitude); - rayDir = new Vec3d(x, y, z); - } + final Vec3d rayDir = new Vec3d(Math.cos(latitude) * Math.cos(longitude), + Math.cos(latitude) * Math.sin(longitude), Math.sin(latitude)); - // Vec3d rayStart = Vec3d.createVectorHelper(soundPos.xCoord + - // rayDir.xCoord * 0.867, soundPos.yCoord + rayDir.yCoord * 0.867, - // soundPos.zCoord + rayDir.zCoord * 0.867); final Vec3d rayStart = new Vec3d(soundPos.xCoord, soundPos.yCoord, soundPos.zCoord); final Vec3d rayEnd = new Vec3d(rayStart.xCoord + rayDir.xCoord * maxDistance, @@ -438,7 +462,7 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi } else { final double newRayLength = lastHitPos.distanceTo(newRayHit.hitVec); - bounceReflectivityRatio[j] += (float) blockReflectivity; + bounceReflectivityRatio[j] += blockReflectivity; totalRayDistance += newRayLength; @@ -450,8 +474,8 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi // 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) { + if (Config.simplerSharedAirspaceSimulation && j == rayBounces - 1 + || !Config.simplerSharedAirspaceSimulation) { final Vec3d finalRayStart = new Vec3d(lastHitPos.xCoord + lastHitNormal.xCoord * 0.01, lastHitPos.yCoord + lastHitNormal.yCoord * 0.01, lastHitPos.zCoord + lastHitNormal.zCoord * 0.01); @@ -495,7 +519,7 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi sharedAirspace *= 64.0f; - if (SoundPhysicsCore.Config.simplerSharedAirspaceSimulation) { + if (Config.simplerSharedAirspaceSimulation) { sharedAirspace *= rcpPrimaryRays; } else { sharedAirspace *= rcpTotalRays; @@ -523,11 +547,13 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi directGain = (float) Math.pow(directCutoff, 0.1); - logEnvironment("Bounce reflectivity 0: " + bounceReflectivityRatio[0] + " bounce reflectivity 1: " - + bounceReflectivityRatio[1] + " bounce reflectivity 2: " + bounceReflectivityRatio[2] - + " bounce reflectivity 3: " + bounceReflectivityRatio[3]); + if (Config.environmentLogging) { + logEnvironment("Bounce reflectivity 0: " + bounceReflectivityRatio[0] + " bounce reflectivity 1: " + + bounceReflectivityRatio[1] + " bounce reflectivity 2: " + bounceReflectivityRatio[2] + + " bounce reflectivity 3: " + bounceReflectivityRatio[3]); + } - sendGain1 *= (float) bounceReflectivityRatio[1]; + sendGain1 *= bounceReflectivityRatio[1]; sendGain2 *= (float) Math.pow(bounceReflectivityRatio[2], 3.0); sendGain3 *= (float) Math.pow(bounceReflectivityRatio[3], 4.0); @@ -541,8 +567,10 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi sendGain2 *= (float) Math.pow(sendCutoff2, 0.1); sendGain3 *= (float) Math.pow(sendCutoff3, 0.1); - logEnvironment("Final environment settings: " + sendGain0 + ", " + sendGain1 + ", " + sendGain2 + ", " - + sendGain3); + if (Config.environmentLogging) { + logEnvironment("Final environment settings: " + sendGain0 + ", " + sendGain1 + ", " + sendGain2 + + ", " + sendGain3); + } if (mc.player.isInWater()) { sendCutoff0 *= 0.4f; @@ -580,7 +608,7 @@ private static void setEnvironment(final int sourceID, final float sendGain0, fi 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); + AL10.alSourcef(sourceID, EFX10.AL_AIR_ABSORPTION_FACTOR, Config.airAbsorption); } /** @@ -630,18 +658,15 @@ protected static void log(final String message) { } protected static void logOcclusion(final String message) { - if (SoundPhysicsCore.Config.occlusionLogging) - System.out.println(logPrefix + " [OCCLUSION] " + ": " + message); + System.out.println(logPrefix + " [OCCLUSION] " + ": " + message); } protected static void logEnvironment(final String message) { - if (SoundPhysicsCore.Config.environmentLogging) - System.out.println(logPrefix + " [ENVIRONMENT] " + ": " + message); + System.out.println(logPrefix + " [ENVIRONMENT] " + ": " + message); } protected static void logGeneral(final String message) { - if (SoundPhysicsCore.Config.debugLogging) - System.out.println(logPrefix + ": " + message); + System.out.println(logPrefix + ": " + message); } protected static void logError(final String errorMessage) { @@ -650,8 +675,9 @@ protected static void logError(final String errorMessage) { protected static boolean checkErrorLog(final String errorMessage) { final int error = AL10.alGetError(); - if (error == 0) + if (error == AL10.AL_NO_ERROR) { return false; + } String errorName; @@ -676,7 +702,7 @@ protected static boolean checkErrorLog(final String errorMessage) { break; } - System.out.println(logPrefix + " [ERROR]: " + errorMessage + " OpenAL error " + errorName); + 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 f508c84a..00000000 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysicsCore.java +++ /dev/null @@ -1,460 +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.MinecraftForge; -import net.minecraftforge.common.config.Configuration; -import net.minecraftforge.fml.client.event.ConfigChangedEvent; -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; - - public static final String modid = "soundphysics"; - public static final String version = "1.0.1"; - - // 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(final FMLPreInitializationEvent event) { - configFile = new Configuration(event.getSuggestedConfigurationFile()); - syncConfig(); - } - - @Mod.EventHandler - public void init(final FMLInitializationEvent event) { - MinecraftForge.EVENT_BUS.register(this); - } - - @SubscribeEvent - public void onConfigChanged(final 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(final String message) { - if (Config.debugLogging) - System.out.println(message); - } - - @Override - public byte[] transform(final String obfuscated, final String deobfuscated, byte[] bytes) { - InsnList toInject = new InsnList(); - InsnList helperList2 = new InsnList(); - - // SoundPhysics.init() in SoundManager.SoundSystemStarterThread - toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "init", "()V", - false)); - bytes = patchMethodInClass(obfuscated, bytes, - new String[] { "net.minecraft.client.audio.SoundManager$SoundSystemStarterThread", "ccq$a" }, - new String[] { "", "" }, - new String[] { "(Lnet/minecraft/client/audio/SoundManager;)V", "(Lccq;)V" }, Opcodes.INVOKESPECIAL, - AbstractInsnNode.METHOD_INSN, new String[] { "", "" }, null, - new InsnList[] { toInject, toInject }, false, 0, 0, false, 0); - - // setLastSoundCategory(var6) in SoundManager.playSound() - 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", false)); - helperList2.add(new VarInsnNode(Opcodes.ALOAD, 7)); - helperList2.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", - "setLastSoundCategory", "(Lno;)V", false)); - bytes = patchMethodInClass(obfuscated, bytes, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, - new String[] { "playSound", "c" }, - new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, Opcodes.INVOKEVIRTUAL, - AbstractInsnNode.METHOD_INSN, new String[] { "setVolume", "setVolume" }, null, - new InsnList[] { toInject, helperList2 }, false, 0, 0, false, 0); - - // setLastSoundName(name) in SoundManager.playSound() - 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;", true)); - toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "net/minecraft/util/ResourceLocation", "toString", - "()Ljava/lang/String;", false)); - toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", - "setLastSoundName", "(Ljava/lang/String;)V", false)); - helperList2 = new InsnList(); - helperList2.add(new VarInsnNode(Opcodes.ALOAD, 1)); - helperList2.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "ccc", "a", "()Lkq;", true)); - helperList2.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "kq", "toString", "()Ljava/lang/String;", false)); - helperList2.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", - "setLastSoundName", "(Ljava/lang/String;)V", false)); - bytes = patchMethodInClass(obfuscated, bytes, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, - new String[] { "playSound", "c" }, - new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, Opcodes.INVOKEVIRTUAL, - AbstractInsnNode.METHOD_INSN, new String[] { "setVolume", "setVolume" }, null, - new InsnList[] { toInject, helperList2 }, false, 0, 0, false, 0); - - // Global volume multiplier - toInject = new InsnList(); - toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", - "globalVolumeMultiplier", "F")); - toInject.add(new InsnNode(Opcodes.FMUL)); - bytes = patchMethodInClass(obfuscated, bytes, new String[] { "net.minecraft.client.audio.SoundManager", "ccq" }, - new String[] { "playSound", "c" }, - new String[] { "(Lnet/minecraft/client/audio/ISound;)V", "(Lccc;)V" }, Opcodes.INVOKESPECIAL, - AbstractInsnNode.METHOD_INSN, new String[] { "getClampedVolume", "e" }, - new String[] { "(Lnet/minecraft/client/audio/ISound;)F", "(Lccc;)F" }, new InsnList[] { toInject }, - false, 0, 0, false, 0); - - // onPlaySound(var6) in paulscode.libraries.SourceLWJGLOpenAL.play() - 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)); - bytes = patchMethodInClass(obfuscated, bytes, new String[] { "paulscode.sound.libraries.SourceLWJGLOpenAL" }, - new String[] { "play" }, new String[] { "(Lpaulscode/sound/Channel;)V" }, Opcodes.INVOKEVIRTUAL, - AbstractInsnNode.METHOD_INSN, new String[] { "play" }, null, new InsnList[] { toInject }, false, 0, 0, - false, 0); - - // attenuation model and rolloff factor - 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")); - bytes = patchMethodInClass(obfuscated, bytes, new String[] { "paulscode.sound.SoundSystem" }, - new String[] { "newSource" }, - new String[] { "(ZLjava/lang/String;Ljava/net/URL;Ljava/lang/String;ZFFFIF)V" }, Opcodes.INVOKESPECIAL, - AbstractInsnNode.METHOD_INSN, new String[] { "" }, null, new InsnList[] { toInject }, true, 2, 0, - false, 0); - - // Multiply sound distance volume play decision by - // SoundPhysics.soundDistanceAllowance - toInject = new InsnList(); - toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", - "soundDistanceAllowance", "D")); - toInject.add(new InsnNode(Opcodes.DMUL)); - bytes = patchMethodInClass(obfuscated, bytes, - new String[] { "net.minecraft.server.management.PlayerList", "mt" }, - new String[] { "sendToAllNearExcept", "a" }, - new String[] { "(Lnet/minecraft/entity/player/EntityPlayer;DDDDILnet/minecraft/network/Packet;)V", - "(Laay;DDDDILfm;)V" }, - Opcodes.DCMPG, AbstractInsnNode.INSN, new String[] { "", "" }, new String[] { "", "" }, - new InsnList[] { toInject }, true, 0, 0, false, 0); - - // Offset entity sound by their eye height - 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)); - helperList2 = new InsnList(); - helperList2.add(new VarInsnNode(Opcodes.ALOAD, 1)); - helperList2.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", - "calculateEntitySoundOffset", "(Lsn;Lnm;)D", false)); - helperList2.add(new InsnNode(Opcodes.DADD)); - helperList2.add(new VarInsnNode(Opcodes.ALOAD, 0)); - bytes = patchMethodInClass(obfuscated, bytes, new String[] { "net.minecraft.entity.Entity", "sn" }, - new String[] { "playSound", "a" }, new String[] { "(Lnet/minecraft/util/SoundEvent;FF)V", "(Lnm;FF)V" }, - Opcodes.INVOKEVIRTUAL, AbstractInsnNode.METHOD_INSN, new String[] { "getSoundCategory", "bC" }, null, - new InsnList[] { toInject, helperList2 }, true, 0, 0, false, -3); - - return bytes; - } - - private byte[] patchMethodInClass(final String currentClassName, final byte[] bytes, - final String[] targetClassNames, final String[] targetMethodNames, final String[] targetMethodSignatures, - final int targetNodeOpcode, final int targetNodeType, final String[] targetInvocationMethodNames, - final String[] targetInvocationMethodSignatures, final InsnList[] instructionsToInjects, - final boolean insertBefore, final int nodesToDeleteBefore, final int nodesToDeleteAfter, - final boolean deleteTargetNode, final 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 - final ClassNode classNode = new ClassNode(); - final 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 - final Iterator methods = classNode.methods.iterator(); - while (methods.hasNext()) { - final MethodNode m = methods.next(); - log("********* Method Name: " + m.name + " Desc: " + m.desc); - - // 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; - - final Iterator iter = m.instructions.iterator(); - - // Loop over the instruction set - while (iter.hasNext()) { - 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) { - final 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; - } - - } - } - } else { - if (currentNode.getType() == targetNodeType) { - log("Found target node for injection: " + targetNodeOpcode); - targetNode = currentNode; - } - } - - } - } - - // 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++) { - final AbstractInsnNode previousNode = targetNode.getPrevious(); - log("Removing Node " + previousNode.getOpcode()); - m.instructions.remove(previousNode); - } - - for (int i = 0; i < nodesToDeleteAfter; i++) { - final 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; - } - } - - final 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 93af47d9..5726442f 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -3,7 +3,7 @@ "modid": "soundphysics", "name": "Sound Physics", "description": "Provides realistic sound attenuation, reverberation, and absorption through blocks.", - "version": "1.0.1", + "version": "1.0.2", "mcversion": "1.11.2", "url": "", "authorList": ["Sonic Ether"] From b95715512a63744dc8f06f4a7aacf1c29bf0590f Mon Sep 17 00:00:00 2001 From: daipenger Date: Thu, 13 Apr 2017 19:59:14 +0200 Subject: [PATCH 18/39] Failed to commit without noticing --- src/main/java/com/sonicether/soundphysics/SPGUIFactory.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java b/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java index c12751f1..59517b65 100644 --- a/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java +++ b/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java @@ -6,7 +6,7 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraftforge.fml.client.IModGuiFactory; -public class SPGUIFactory implements IModGuiFactory { +public class SPGuiFactory implements IModGuiFactory { @Override public void initialize(final Minecraft minecraftInstance) { @@ -14,7 +14,7 @@ public void initialize(final Minecraft minecraftInstance) { @Override public Class mainConfigGuiClass() { - return SPConfigGUI.class; + return SPGuiConfig.class; } @Override @@ -24,7 +24,7 @@ public Set runtimeGuiCategories() { @SuppressWarnings("deprecation") @Override - public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { + public RuntimeOptionGuiHandler getHandlerFor(final RuntimeOptionCategoryElement element) { return null; } From 55f5c1974912cd2c078a87a85192c1975ee856ac Mon Sep 17 00:00:00 2001 From: daipenger Date: Thu, 13 Apr 2017 21:29:22 +0200 Subject: [PATCH 19/39] Build upon the latest forge version --- build.gradle | 4 ++-- .../com/sonicether/soundphysics/SPGUIFactory.java | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index c83f83f6..0a08a042 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ jar { } minecraft { - version = "1.11.2-13.20.0.2201" + version = "1.11.2-13.20.0.2282" runDir = "run" // the mappings can be changed at any time, and must be in the following format. @@ -74,4 +74,4 @@ processResources { from(sourceSets.main.resources.srcDirs) { exclude 'mcmod.info' } -} \ 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 index 59517b65..48249ff5 100644 --- a/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java +++ b/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java @@ -9,7 +9,17 @@ public class SPGuiFactory implements IModGuiFactory { @Override - public void initialize(final Minecraft minecraftInstance) { + public void initialize(Minecraft minecraftInstance) { + } + + @Override + public boolean hasConfigGui() { + return true; + } + + @Override + public GuiScreen createConfigGui(GuiScreen parentScreen) { + return new SPGuiConfig(parentScreen); } @Override @@ -22,9 +32,8 @@ public Set runtimeGuiCategories() { return null; } - @SuppressWarnings("deprecation") @Override - public RuntimeOptionGuiHandler getHandlerFor(final RuntimeOptionCategoryElement element) { + public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { return null; } From 949c6be8cf183efb4b52645e902f83150a0765f7 Mon Sep 17 00:00:00 2001 From: daipenger Date: Thu, 13 Apr 2017 21:39:47 +0200 Subject: [PATCH 20/39] Fix git lowercase bug, step 1 --- ...PGUIFactory.java => SPGuiFactoryTEMP.java} | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) rename src/main/java/com/sonicether/soundphysics/{SPGUIFactory.java => SPGuiFactoryTEMP.java} (89%) diff --git a/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java b/src/main/java/com/sonicether/soundphysics/SPGuiFactoryTEMP.java similarity index 89% rename from src/main/java/com/sonicether/soundphysics/SPGUIFactory.java rename to src/main/java/com/sonicether/soundphysics/SPGuiFactoryTEMP.java index 48249ff5..be5110aa 100644 --- a/src/main/java/com/sonicether/soundphysics/SPGUIFactory.java +++ b/src/main/java/com/sonicether/soundphysics/SPGuiFactoryTEMP.java @@ -1,40 +1,40 @@ -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 Class mainConfigGuiClass() { - return SPGuiConfig.class; - } - - @Override - public Set runtimeGuiCategories() { - return null; - } - - @Override - public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { - return null; - } - -} +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 SPGuiFactoryTEMP 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 Class mainConfigGuiClass() { + return SPGuiConfig.class; + } + + @Override + public Set runtimeGuiCategories() { + return null; + } + + @Override + public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { + return null; + } + +} From 7bd0d5018784b0a40e8be10bdc6fb86bc9da05cf Mon Sep 17 00:00:00 2001 From: daipenger Date: Thu, 13 Apr 2017 21:40:25 +0200 Subject: [PATCH 21/39] Fix git lowercase bug, step 2 --- .../soundphysics/{SPGuiFactoryTEMP.java => SPGuiFactory.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/com/sonicether/soundphysics/{SPGuiFactoryTEMP.java => SPGuiFactory.java} (92%) diff --git a/src/main/java/com/sonicether/soundphysics/SPGuiFactoryTEMP.java b/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java similarity index 92% rename from src/main/java/com/sonicether/soundphysics/SPGuiFactoryTEMP.java rename to src/main/java/com/sonicether/soundphysics/SPGuiFactory.java index be5110aa..3cce6d4d 100644 --- a/src/main/java/com/sonicether/soundphysics/SPGuiFactoryTEMP.java +++ b/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java @@ -6,7 +6,7 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraftforge.fml.client.IModGuiFactory; -public class SPGuiFactoryTEMP implements IModGuiFactory { +public class SPGuiFactory implements IModGuiFactory { @Override public void initialize(Minecraft minecraftInstance) { From b035597c6f6c92826bc140469d36d32a5d200809 Mon Sep 17 00:00:00 2001 From: daipenger Date: Thu, 13 Apr 2017 21:41:45 +0200 Subject: [PATCH 22/39] Add back suppressing deprecation --- src/main/java/com/sonicether/soundphysics/SPGuiFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java b/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java index 3cce6d4d..e508c7e0 100644 --- a/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java +++ b/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java @@ -32,6 +32,7 @@ public Set runtimeGuiCategories() { return null; } + @SuppressWarnings("deprecation") @Override public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { return null; From 2b2053afe3be633163071e4485a7496f686e972d Mon Sep 17 00:00:00 2001 From: J4D3N Date: Sun, 18 Jun 2017 15:08:45 +0100 Subject: [PATCH 23/39] Update to 1.12 --- build.gradle | 8 +-- .../soundphysics/CoreModInjector.java | 24 ++++---- .../soundphysics/CoreModLoader.java | 2 +- .../sonicether/soundphysics/SoundPhysics.java | 58 +++++++++---------- src/main/resources/mcmod.info | 4 +- 5 files changed, 48 insertions(+), 48 deletions(-) diff --git a/build.gradle b/build.gradle index 0a08a042..4a293b08 100644 --- a/build.gradle +++ b/build.gradle @@ -4,13 +4,13 @@ buildscript { maven { url = "http://files.minecraftforge.net/maven" } } dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:2.2-SNAPSHOT' + 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.11.2" +version = "1.12" archivesBaseName = "Sound-Physics" jar { @@ -21,7 +21,7 @@ jar { } minecraft { - version = "1.11.2-13.20.0.2282" + version = "1.12-14.21.0.2334" runDir = "run" // the mappings can be changed at any time, and must be in the following format. @@ -29,7 +29,7 @@ minecraft { // stable_# stables are built at the discretion of the MCP team. // Use non-default mappings at your own risk. they may not always work. // simply re-run your setup task after changing the mappings to update your workspace. - mappings = "snapshot_20161220" + mappings = "snapshot_20170618" // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. } diff --git a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java index 4713a10c..6fab208e 100644 --- a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java @@ -27,27 +27,27 @@ public byte[] transform(final String obfuscated, final String deobfuscated, byte toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "init", "()V", false)); - bytes = patchMethodInClass(obfuscated, bytes, "ccq$a", "", "(Lccq;)V", Opcodes.INVOKESPECIAL, + bytes = patchMethodInClass(obfuscated, bytes, "chk$a", "", "(Lchk;)V", Opcodes.INVOKESPECIAL, AbstractInsnNode.METHOD_INSN, "", null, toInject, false, 0, 0, false, 0); // setLastSoundCategory(var6) in SoundManager.playSound() toInject = new InsnList(); toInject.add(new VarInsnNode(Opcodes.ALOAD, 7)); toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", - "setLastSoundCategory", "(Lno;)V", false)); + "setLastSoundCategory", "(Lqe;)V", false)); - bytes = patchMethodInClass(obfuscated, bytes, "ccq", "c", "(Lccc;)V", Opcodes.INVOKEVIRTUAL, + bytes = patchMethodInClass(obfuscated, bytes, "chk", "c", "(Lcgr;)V", Opcodes.INVOKEVIRTUAL, AbstractInsnNode.METHOD_INSN, "setVolume", null, toInject, false, 0, 0, false, 0); // setLastSoundName(name) in SoundManager.playSound() toInject = new InsnList(); toInject.add(new VarInsnNode(Opcodes.ALOAD, 1)); - toInject.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "ccc", "a", "()Lkq;", true)); - toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "kq", "toString", "()Ljava/lang/String;", false)); + toInject.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "cgr", "a", "()Lnd;", true)); + toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "nd", "toString", "()Ljava/lang/String;", false)); toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "setLastSoundName", "(Ljava/lang/String;)V", false)); - bytes = patchMethodInClass(obfuscated, bytes, "ccq", "c", "(Lccc;)V", Opcodes.INVOKEVIRTUAL, + bytes = patchMethodInClass(obfuscated, bytes, "chk", "c", "(Lcgr;)V", Opcodes.INVOKEVIRTUAL, AbstractInsnNode.METHOD_INSN, "setVolume", null, toInject, false, 0, 0, false, 0); // Global volume multiplier @@ -56,8 +56,8 @@ public byte[] transform(final String obfuscated, final String deobfuscated, byte "globalVolumeMultiplier", "F")); toInject.add(new InsnNode(Opcodes.FMUL)); - bytes = patchMethodInClass(obfuscated, bytes, "ccq", "c", "(Lccc;)V", Opcodes.INVOKESPECIAL, - AbstractInsnNode.METHOD_INSN, "e", "(Lccc;)F", toInject, false, 0, 0, false, 0); + bytes = patchMethodInClass(obfuscated, bytes, "chk", "c", "(Lcgr;)V", Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, "e", "(Lcgr;)F", toInject, false, 0, 0, false, 0); // onPlaySound(var6) in paulscode.libraries.SourceLWJGLOpenAL.play() toInject = new InsnList(); @@ -105,19 +105,19 @@ public byte[] transform(final String obfuscated, final String deobfuscated, byte "soundDistanceAllowance", "D")); toInject.add(new InsnNode(Opcodes.DMUL)); - bytes = patchMethodInClass(obfuscated, bytes, "mt", "a", "(Laay;DDDDILfm;)V", Opcodes.DCMPG, + bytes = patchMethodInClass(obfuscated, bytes, "pj", "a", "(Laeb;DDDDILht;)V", Opcodes.DCMPG, AbstractInsnNode.INSN, "", "", toInject, true, 0, 0, false, 0); // Offset entity sound by their eye height toInject = new InsnList(); toInject.add(new VarInsnNode(Opcodes.ALOAD, 1)); toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", - "calculateEntitySoundOffset", "(Lsn;Lnm;)D", false)); + "calculateEntitySoundOffset", "(Lve;Lqc;)D", false)); toInject.add(new InsnNode(Opcodes.DADD)); toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); - bytes = patchMethodInClass(obfuscated, bytes, "sn", "a", "(Lnm;FF)V", Opcodes.INVOKEVIRTUAL, - AbstractInsnNode.METHOD_INSN, "bC", null, toInject, true, 0, 0, false, -3); + bytes = patchMethodInClass(obfuscated, bytes, "ve", "a", "(Lqc;FF)V", Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, "bK", null, toInject, true, 0, 0, false, -3); return bytes; } diff --git a/src/main/java/com/sonicether/soundphysics/CoreModLoader.java b/src/main/java/com/sonicether/soundphysics/CoreModLoader.java index 30b5d65d..faff1d41 100644 --- a/src/main/java/com/sonicether/soundphysics/CoreModLoader.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModLoader.java @@ -5,7 +5,7 @@ import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.MCVersion; -@MCVersion(value = "1.11.2") +@MCVersion(value = "1.12") public class CoreModLoader implements IFMLLoadingPlugin { @Override diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index caf13700..4049cb81 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -29,7 +29,7 @@ public class SoundPhysics { public static final String modid = "soundphysics"; - public static final String version = "1.0.2"; + public static final String version = "1.0.3"; @Instance(modid) public static SoundPhysics instance; @@ -259,9 +259,9 @@ private static Vec3d reflect(final Vec3d dir, final Vec3d normal) { // dir - 2.0 * dot(normal, dir) * normal final double dot = dir.dotProduct(normal); - final double x = dir.xCoord - 2.0 * dot * normal.xCoord; - final double y = dir.yCoord - 2.0 * dot * normal.yCoord; - final double z = dir.zCoord - 2.0 * dot * normal.zCoord; + final double x = dir.x - 2.0 * dot * normal.x; + final double y = dir.y - 2.0 * dot * normal.y; + final double z = dir.z - 2.0 * dot * normal.z; return new Vec3d(x, y, z); } @@ -287,9 +287,9 @@ private static Vec3d offsetSoundByName(final double soundX, final double soundY, // escaping. Offset the ray start position towards the player by the // diagonal half length of a cube - tempNormX = playerPos.xCoord - soundX; - tempNormY = playerPos.yCoord - soundY; - tempNormZ = playerPos.zCoord - soundZ; + 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; @@ -327,10 +327,10 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi final Vec3d normalToPlayer = playerPos.subtract(soundPos).normalize(); if (Config.debugLogging) { - logGeneral("Player pos: " + playerPos.xCoord + ", " + playerPos.yCoord + ", " + playerPos.zCoord - + " Sound Pos: " + soundPos.xCoord + ", " + soundPos.yCoord + ", " + soundPos.zCoord - + " To player vector: " + normalToPlayer.xCoord + ", " + normalToPlayer.yCoord + ", " - + normalToPlayer.zCoord); + logGeneral("Player pos: " + playerPos.x + ", " + playerPos.y + ", " + playerPos.z + + " Sound Pos: " + soundPos.x + ", " + soundPos.y + ", " + soundPos.z + + " To player vector: " + normalToPlayer.x + ", " + normalToPlayer.y + ", " + + normalToPlayer.z); } Vec3d rayOrigin = soundPos; @@ -354,19 +354,19 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi } if (Config.occlusionLogging) { - logOcclusion(blockHit.getUnlocalizedName() + " " + rayHit.hitVec.xCoord + ", " + rayHit.hitVec.yCoord - + ", " + rayHit.hitVec.zCoord); + logOcclusion(blockHit.getUnlocalizedName() + " " + rayHit.hitVec.x + ", " + rayHit.hitVec.y + + ", " + rayHit.hitVec.z); } occlusionAccumulation += blockOcclusion; - rayOrigin = new Vec3d(rayHit.hitVec.xCoord + normalToPlayer.xCoord * 0.1, - rayHit.hitVec.yCoord + normalToPlayer.yCoord * 0.1, - rayHit.hitVec.zCoord + normalToPlayer.zCoord * 0.1); + rayOrigin = new Vec3d(rayHit.hitVec.x + normalToPlayer.x * 0.1, + rayHit.hitVec.y + normalToPlayer.y * 0.1, + rayHit.hitVec.z + normalToPlayer.z * 0.1); if (Config.occlusionLogging) { logOcclusion( - "New trace position: " + rayOrigin.xCoord + ", " + rayOrigin.yCoord + ", " + rayOrigin.zCoord); + "New trace position: " + rayOrigin.x + ", " + rayOrigin.y + ", " + rayOrigin.z); } } @@ -422,10 +422,10 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi 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.xCoord, soundPos.yCoord, soundPos.zCoord); + final Vec3d rayStart = new Vec3d(soundPos.x, soundPos.y, soundPos.z); - final Vec3d rayEnd = new Vec3d(rayStart.xCoord + rayDir.xCoord * maxDistance, - rayStart.yCoord + rayDir.yCoord * maxDistance, rayStart.zCoord + rayDir.zCoord * maxDistance); + 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); @@ -444,12 +444,12 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi for (int j = 0; j < rayBounces; j++) { final Vec3d newRayDir = reflect(lastRayDir, lastHitNormal); // Vec3d newRayDir = lastHitNormal; - final Vec3d newRayStart = new Vec3d(lastHitPos.xCoord + lastHitNormal.xCoord * 0.01, - lastHitPos.yCoord + lastHitNormal.yCoord * 0.01, - lastHitPos.zCoord + lastHitNormal.zCoord * 0.01); - final Vec3d newRayEnd = new Vec3d(newRayStart.xCoord + newRayDir.xCoord * maxDistance, - newRayStart.yCoord + newRayDir.yCoord * maxDistance, - newRayStart.zCoord + newRayDir.zCoord * maxDistance); + 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); @@ -476,9 +476,9 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi // share airspace. if (Config.simplerSharedAirspaceSimulation && j == rayBounces - 1 || !Config.simplerSharedAirspaceSimulation) { - final Vec3d finalRayStart = new Vec3d(lastHitPos.xCoord + lastHitNormal.xCoord * 0.01, - lastHitPos.yCoord + lastHitNormal.yCoord * 0.01, - lastHitPos.zCoord + lastHitNormal.zCoord * 0.01); + 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); diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 5726442f..91d551a3 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -3,8 +3,8 @@ "modid": "soundphysics", "name": "Sound Physics", "description": "Provides realistic sound attenuation, reverberation, and absorption through blocks.", - "version": "1.0.2", - "mcversion": "1.11.2", + "version": "1.0.3", + "mcversion": "1.12", "url": "", "authorList": ["Sonic Ether"] } From d35d778df5d5d50829068389d4a04780668bf7e4 Mon Sep 17 00:00:00 2001 From: daipenger Date: Sun, 18 Jun 2017 16:48:43 +0200 Subject: [PATCH 24/39] Match mappings with forge build, build with 1.8 --- build.gradle | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4a293b08..a49cc919 100644 --- a/build.gradle +++ b/build.gradle @@ -20,6 +20,11 @@ jar { } } +sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. +compileJava { + sourceCompatibility = targetCompatibility = '1.8' +} + minecraft { version = "1.12-14.21.0.2334" runDir = "run" @@ -29,7 +34,7 @@ minecraft { // stable_# stables are built at the discretion of the MCP team. // Use non-default mappings at your own risk. they may not always work. // simply re-run your setup task after changing the mappings to update your workspace. - mappings = "snapshot_20170618" + mappings = "snapshot_20170617" // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. } From e0ede37678f113478c412a6fd5f62b54a784968b Mon Sep 17 00:00:00 2001 From: daipenger Date: Sun, 18 Jun 2017 16:54:29 +0200 Subject: [PATCH 25/39] Include gradle directory (Issue #4) --- .gitignore | 5 +- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 52271 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 +++++++++++++++++++++++ gradlew.bat | 90 +++++++++++++ 5 files changed, 261 insertions(+), 4 deletions(-) create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat diff --git a/.gitignore b/.gitignore index d010fc61..322e5e18 100644 --- a/.gitignore +++ b/.gitignore @@ -16,10 +16,7 @@ out # gradle build .gradle -gradle # other eclipse -run -gradlew -gradlew.bat \ No newline at end of file +run \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..30d399d8d2bf522ff5de94bf434a7cc43a9a74b5 GIT binary patch literal 52271 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 p \(.*\)$'` + 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 From d3cfc8bd965d95a4e6628ce6a9931078eab6c025 Mon Sep 17 00:00:00 2001 From: daipenger Date: Mon, 19 Jun 2017 21:10:38 +0200 Subject: [PATCH 26/39] Optimize Injector (check first, create InsnLists then) --- .../soundphysics/CoreModInjector.java | 237 ++++++++++-------- 1 file changed, 127 insertions(+), 110 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java index 6fab208e..d440cdaf 100644 --- a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java @@ -21,120 +21,137 @@ public class CoreModInjector implements IClassTransformer { @Override public byte[] transform(final String obfuscated, final String deobfuscated, byte[] bytes) { - InsnList toInject = new InsnList(); - - // SoundPhysics.init() in SoundManager.SoundSystemStarterThread - toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", "init", "()V", - false)); - - bytes = patchMethodInClass(obfuscated, bytes, "chk$a", "", "(Lchk;)V", Opcodes.INVOKESPECIAL, - AbstractInsnNode.METHOD_INSN, "", null, toInject, false, 0, 0, false, 0); - - // setLastSoundCategory(var6) in SoundManager.playSound() - toInject = new InsnList(); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 7)); - toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", - "setLastSoundCategory", "(Lqe;)V", false)); - - bytes = patchMethodInClass(obfuscated, bytes, "chk", "c", "(Lcgr;)V", Opcodes.INVOKEVIRTUAL, - AbstractInsnNode.METHOD_INSN, "setVolume", null, toInject, false, 0, 0, false, 0); - - // setLastSoundName(name) in SoundManager.playSound() - toInject = new InsnList(); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 1)); - toInject.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "cgr", "a", "()Lnd;", true)); - toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "nd", "toString", "()Ljava/lang/String;", false)); - toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", - "setLastSoundName", "(Ljava/lang/String;)V", false)); - - bytes = patchMethodInClass(obfuscated, bytes, "chk", "c", "(Lcgr;)V", Opcodes.INVOKEVIRTUAL, - AbstractInsnNode.METHOD_INSN, "setVolume", null, toInject, false, 0, 0, false, 0); - - // Global volume multiplier - toInject = new InsnList(); - toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", - "globalVolumeMultiplier", "F")); - toInject.add(new InsnNode(Opcodes.FMUL)); - - bytes = patchMethodInClass(obfuscated, bytes, "chk", "c", "(Lcgr;)V", Opcodes.INVOKESPECIAL, - AbstractInsnNode.METHOD_INSN, "e", "(Lcgr;)F", toInject, false, 0, 0, false, 0); - - // onPlaySound(var6) in paulscode.libraries.SourceLWJGLOpenAL.play() - 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)); - - bytes = patchMethodInClass(obfuscated, bytes, "paulscode.sound.libraries.SourceLWJGLOpenAL", "play", - "(Lpaulscode/sound/Channel;)V", Opcodes.INVOKEVIRTUAL, AbstractInsnNode.METHOD_INSN, "play", null, - toInject, false, 0, 0, false, 0); - - // attenuation model and rolloff factor - 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")); - - bytes = patchMethodInClass(obfuscated, bytes, "paulscode.sound.SoundSystem", "newSource", - "(ZLjava/lang/String;Ljava/net/URL;Ljava/lang/String;ZFFFIF)V", Opcodes.INVOKESPECIAL, - AbstractInsnNode.METHOD_INSN, "", null, toInject, true, 2, 0, false, 0); - - // Multiply sound distance volume play decision by - // SoundPhysics.soundDistanceAllowance - toInject = new InsnList(); - toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", - "soundDistanceAllowance", "D")); - toInject.add(new InsnNode(Opcodes.DMUL)); - - bytes = patchMethodInClass(obfuscated, bytes, "pj", "a", "(Laeb;DDDDILht;)V", Opcodes.DCMPG, - AbstractInsnNode.INSN, "", "", toInject, true, 0, 0, false, 0); - - // Offset entity sound by their eye height - toInject = new InsnList(); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 1)); - toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", - "calculateEntitySoundOffset", "(Lve;Lqc;)D", false)); - toInject.add(new InsnNode(Opcodes.DADD)); - toInject.add(new VarInsnNode(Opcodes.ALOAD, 0)); - - bytes = patchMethodInClass(obfuscated, bytes, "ve", "a", "(Lqc;FF)V", Opcodes.INVOKEVIRTUAL, - AbstractInsnNode.METHOD_INSN, "bK", null, toInject, true, 0, 0, false, -3); + if (obfuscated.equals("chk$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, "", "(Lchk;)V", Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, "", null, toInject, false, 0, 0, false, 0); + } else + + if (obfuscated.equals("chk")) { + // Inside SoundManager + InsnList toInject = new InsnList(); + + toInject.add(new VarInsnNode(Opcodes.ALOAD, 7)); + toInject.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/sonicether/soundphysics/SoundPhysics", + "setLastSoundCategory", "(Lqe;)V", false)); + + // Target method: playSound + bytes = patchMethodInClass(obfuscated, bytes, "c", "(Lcgr;)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, "cgr", "a", "()Lnd;", true)); + toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "nd", "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", "(Lcgr;)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 + bytes = patchMethodInClass(obfuscated, bytes, "c", "(Lcgr;)V", Opcodes.INVOKESPECIAL, + AbstractInsnNode.METHOD_INSN, "e", "(Lcgr;)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("pj")) { + // 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", "(Laeb;DDDDILht;)V", Opcodes.DCMPG, + AbstractInsnNode.INSN, "", "", toInject, true, 0, 0, false, 0); + } else + + if (obfuscated.equals("ve")) { + // 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", "(Lve;Lqc;)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", "(Lqc;FF)V", Opcodes.INVOKEVIRTUAL, + AbstractInsnNode.METHOD_INSN, "bK", null, toInject, true, 0, 0, false, -3); + } return bytes; } - private byte[] patchMethodInClass(final String obfuscatedClassName, final byte[] bytes, final String targetClass, - 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) { - - // If this is not the target class, leave! - if (!obfuscatedClassName.equals(targetClass)) { - return bytes; - } - - log("################################################################# Patching Class: " + targetClass); + 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) { + log("Patching Class: " + className); // Setup ASM class manipulation stuff final ClassNode classNode = new ClassNode(); From 2a16629e8e1d2b587ba1293855cd68c73746ed43 Mon Sep 17 00:00:00 2001 From: daipenger Date: Mon, 19 Jun 2017 21:15:55 +0200 Subject: [PATCH 27/39] Change logging --- .../soundphysics/CoreModInjector.java | 10 ++-- .../sonicether/soundphysics/SoundPhysics.java | 53 +++++++++---------- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java index d440cdaf..fd0567c4 100644 --- a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java @@ -151,7 +151,7 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St final String targetInvocationMethodName, final String targetInvocationMethodSignature, final InsnList instructionsToInject, final boolean insertBefore, final int nodesToDeleteBefore, final int nodesToDeleteAfter, final boolean deleteTargetNode, final int targetNodeOffset) { - log("Patching Class: " + className); + log("//// Patching Class: " + className); // Setup ASM class manipulation stuff final ClassNode classNode = new ClassNode(); @@ -163,11 +163,11 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St final Iterator methods = classNode.methods.iterator(); while (methods.hasNext()) { final MethodNode m = methods.next(); - log("********* Method Name: " + m.name + " Desc: " + m.desc); + log("@" + m.name + " " + m.desc); // Check if this is the method name and the signature matches if (m.name.equals(targetMethod) && m.desc.equals(targetMethodSignature)) { - log("*************************************** Inside target method: " + targetMethod); + log("Inside target method: " + targetMethod); AbstractInsnNode currentNode = null; AbstractInsnNode targetNode = null; @@ -250,7 +250,7 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St m.instructions.remove(targetNode); } - log("Patching complete!----------------------------------------------------------------------------------------"); + log("//// Class finished: " + className); break; } @@ -263,7 +263,7 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St private void log(final String message) { if (Config.debugLogging) { - System.out.println(message); + SoundPhysics.log(message); } } diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 4049cb81..36c03444 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -307,7 +307,8 @@ private static Vec3d offsetSoundByName(final double soundX, final double soundY, @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) { - // Menu clicks, posY <= 0 as a condition has to be there: Ingame menu clicks do have a player and world present + // Menu clicks, 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; } @@ -327,10 +328,9 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi final Vec3d normalToPlayer = playerPos.subtract(soundPos).normalize(); if (Config.debugLogging) { - logGeneral("Player pos: " + playerPos.x + ", " + playerPos.y + ", " + playerPos.z - + " Sound Pos: " + soundPos.x + ", " + soundPos.y + ", " + soundPos.z - + " To player vector: " + normalToPlayer.x + ", " + normalToPlayer.y + ", " - + normalToPlayer.z); + logGeneral("Player pos: " + playerPos.x + ", " + playerPos.y + ", " + playerPos.z + " Sound Pos: " + + soundPos.x + ", " + soundPos.y + ", " + soundPos.z + " To player vector: " + + normalToPlayer.x + ", " + normalToPlayer.y + ", " + normalToPlayer.z); } Vec3d rayOrigin = soundPos; @@ -354,19 +354,17 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi } if (Config.occlusionLogging) { - logOcclusion(blockHit.getUnlocalizedName() + " " + rayHit.hitVec.x + ", " + rayHit.hitVec.y - + ", " + rayHit.hitVec.z); + logOcclusion(blockHit.getUnlocalizedName() + " " + rayHit.hitVec.x + ", " + rayHit.hitVec.y + ", " + + rayHit.hitVec.z); } occlusionAccumulation += blockOcclusion; - rayOrigin = new Vec3d(rayHit.hitVec.x + normalToPlayer.x * 0.1, - rayHit.hitVec.y + normalToPlayer.y * 0.1, + rayOrigin = new Vec3d(rayHit.hitVec.x + normalToPlayer.x * 0.1, rayHit.hitVec.y + normalToPlayer.y * 0.1, rayHit.hitVec.z + normalToPlayer.z * 0.1); if (Config.occlusionLogging) { - logOcclusion( - "New trace position: " + rayOrigin.x + ", " + rayOrigin.y + ", " + rayOrigin.z); + logOcclusion("New trace position: " + rayOrigin.x + ", " + rayOrigin.y + ", " + rayOrigin.z); } } @@ -424,8 +422,8 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi 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 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); @@ -445,11 +443,9 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi 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); + 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); + newRayStart.y + newRayDir.y * maxDistance, newRayStart.z + newRayDir.z * maxDistance); final RayTraceResult newRayHit = mc.world.rayTraceBlocks(newRayStart, newRayEnd, true); @@ -477,8 +473,7 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi 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); + lastHitPos.y + lastHitNormal.y * 0.01, lastHitPos.z + lastHitNormal.z * 0.01); final RayTraceResult finalRayHit = mc.world.rayTraceBlocks(finalRayStart, playerPos, true); @@ -653,24 +648,24 @@ protected static void setReverbParams(final ReverbParams r, final int auxFXSlot, EFX10.alAuxiliaryEffectSloti(auxFXSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbSlot); } - protected static void log(final String message) { - System.out.println(logPrefix + ": " + message); + public static void log(final String message) { + System.out.println(logPrefix.concat(" : ").concat(message)); } - protected static void logOcclusion(final String message) { - System.out.println(logPrefix + " [OCCLUSION] " + ": " + message); + public static void logOcclusion(final String message) { + System.out.println(logPrefix.concat(" [OCCLUSION] : ").concat(message)); } - protected static void logEnvironment(final String message) { - System.out.println(logPrefix + " [ENVIRONMENT] " + ": " + message); + public static void logEnvironment(final String message) { + System.out.println(logPrefix.concat(" [ENVIRONMENT] : ").concat(message)); } - protected static void logGeneral(final String message) { - System.out.println(logPrefix + ": " + message); + public static void logGeneral(final String message) { + System.out.println(logPrefix.concat(": ").concat(message)); } - protected static void logError(final 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(final String errorMessage) { From 9b61ffb1dfc1d7210259d67387b6bdd544e1a67a Mon Sep 17 00:00:00 2001 From: daipenger Date: Tue, 20 Jun 2017 10:56:35 +0200 Subject: [PATCH 28/39] Clean up patchMethod --- .../soundphysics/CoreModInjector.java | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java index fd0567c4..3864294b 100644 --- a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java @@ -160,36 +160,35 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St // Now we loop over all of the methods declared inside the class until // we get to the target method name - final Iterator methods = classNode.methods.iterator(); - while (methods.hasNext()) { - final MethodNode m = methods.next(); + final Iterator methodIterator = classNode.methods.iterator(); + while (methodIterator.hasNext()) { + final MethodNode m = methodIterator.next(); log("@" + m.name + " " + m.desc); // Check if this is the method name and the signature matches if (m.name.equals(targetMethod) && m.desc.equals(targetMethodSignature)) { log("Inside target method: " + targetMethod); - AbstractInsnNode currentNode = null; AbstractInsnNode targetNode = null; - final ListIterator iter = m.instructions.iterator(); - // Loop over the instruction set - while (iter.hasNext()) { - currentNode = iter.next(); + 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; - // 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; + // Due to collisions, do not put break + // statements here! } } @@ -198,17 +197,16 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St if (currentNode.getType() == targetNodeType) { log("Found target node for injection: " + targetNodeOpcode); targetNode = currentNode; + // Due to collisions, do not put break + // statements here! } } - // TODO: BREAK STATEMENTS! BUT MAY NOT WORK IF THERE ARE - // MORE THAN ONE MATCHING TARGET NODES! (offsets have to - // be corrected) - } } if (targetNode == null) { + SoundPhysics.logError("Target node not found!" + className); break; } @@ -223,10 +221,6 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St } } - if (targetNode == null) { - break; - } - // If we've found the target, inject the instructions! for (int i = 0; i < nodesToDeleteBefore; i++) { final AbstractInsnNode previousNode = targetNode.getPrevious(); @@ -250,12 +244,12 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St m.instructions.remove(targetNode); } - log("//// Class finished: " + className); - break; } } + log("//// Class finished: " + className); + final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); classNode.accept(writer); return writer.toByteArray(); From d14442e89100999b88fc92d364f22b3d6a3f0bc9 Mon Sep 17 00:00:00 2001 From: daipenger Date: Tue, 20 Jun 2017 21:18:37 +0200 Subject: [PATCH 29/39] Fix the pesky stereo sound files bug #8 and #9 are related to this --- src/main/java/com/sonicether/soundphysics/Config.java | 3 --- .../java/com/sonicether/soundphysics/CoreModInjector.java | 7 +++---- .../java/com/sonicether/soundphysics/ReverbParams.java | 8 ++++---- .../java/com/sonicether/soundphysics/SoundPhysics.java | 4 ---- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/Config.java b/src/main/java/com/sonicether/soundphysics/Config.java index 3335a7c8..4686f7cc 100644 --- a/src/main/java/com/sonicether/soundphysics/Config.java +++ b/src/main/java/com/sonicether/soundphysics/Config.java @@ -17,7 +17,6 @@ public class Config { private Configuration forgeConfig; // 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; @@ -82,8 +81,6 @@ public List getConfigElements() { 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, diff --git a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java index 3864294b..c3d43c2a 100644 --- a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java @@ -101,14 +101,13 @@ public byte[] transform(final String obfuscated, final String deobfuscated, byte 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")); + "globalVolumeMultiplier", "F")); + toInject.add(new InsnNode(Opcodes.FMUL)); // 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); + AbstractInsnNode.METHOD_INSN, "", null, toInject, true, 0, 0, false, 0); } else if (obfuscated.equals("pj")) { diff --git a/src/main/java/com/sonicether/soundphysics/ReverbParams.java b/src/main/java/com/sonicether/soundphysics/ReverbParams.java index 97f269f0..606cff9d 100644 --- a/src/main/java/com/sonicether/soundphysics/ReverbParams.java +++ b/src/main/java/com/sonicether/soundphysics/ReverbParams.java @@ -28,7 +28,7 @@ public static ReverbParams getReverb0() { r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.011f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.16f * Config.rolloffFactor; + r.roomRolloffFactor = 0.16f; return r; } @@ -46,7 +46,7 @@ public static ReverbParams getReverb1() { r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.011f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.15f * Config.rolloffFactor; + r.roomRolloffFactor = 0.15f; return r; } @@ -64,7 +64,7 @@ public static ReverbParams getReverb2() { r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.021f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.13f * Config.rolloffFactor; + r.roomRolloffFactor = 0.13f; return r; } @@ -82,7 +82,7 @@ public static ReverbParams getReverb3() { r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.021f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.11f * Config.rolloffFactor; + r.roomRolloffFactor = 0.11f; return r; } diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 36c03444..a4a35765 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -23,7 +23,6 @@ import net.minecraftforge.fml.common.Mod.Instance; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; -import paulscode.sound.SoundSystemConfig; @Mod(modid = SoundPhysics.modid, version = SoundPhysics.version, guiFactory = "com.sonicether.soundphysics.SPGuiFactory") public class SoundPhysics { @@ -71,8 +70,6 @@ public void init(final FMLInitializationEvent event) { // 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 = Config.rolloffFactor; public static float globalVolumeMultiplier = 4.0f; public static float globalReverbMultiplier = 0.7f * Config.globalReverbGain; public static double soundDistanceAllowance = Config.soundDistanceAllowance; @@ -87,7 +84,6 @@ public static void init() { } public static void applyConfigChanges() { - globalRolloffFactor = Config.rolloffFactor; globalReverbMultiplier = 0.7f * Config.globalReverbGain; soundDistanceAllowance = Config.soundDistanceAllowance; From 7918cb3f17c5a1ca7d54d5f30611f7ff185fba8a Mon Sep 17 00:00:00 2001 From: daipenger Date: Tue, 20 Jun 2017 21:19:52 +0200 Subject: [PATCH 30/39] Version 1.0.4 --- src/main/java/com/sonicether/soundphysics/SoundPhysics.java | 2 +- src/main/resources/mcmod.info | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index a4a35765..89295f62 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -28,7 +28,7 @@ public class SoundPhysics { public static final String modid = "soundphysics"; - public static final String version = "1.0.3"; + public static final String version = "1.0.4"; @Instance(modid) public static SoundPhysics instance; diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 91d551a3..cb9e737d 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -3,7 +3,7 @@ "modid": "soundphysics", "name": "Sound Physics", "description": "Provides realistic sound attenuation, reverberation, and absorption through blocks.", - "version": "1.0.3", + "version": "1.0.4", "mcversion": "1.12", "url": "", "authorList": ["Sonic Ether"] From b732f33ddb6d50f62cb660295457e4f641780d8f Mon Sep 17 00:00:00 2001 From: daipenger Date: Wed, 16 Aug 2017 11:04:30 +0200 Subject: [PATCH 31/39] Update to 1.12.1, small stuff clientSideOnly set Added me as author --- build.gradle | 6 ++-- .../soundphysics/CoreModInjector.java | 32 +++++++++---------- .../soundphysics/CoreModLoader.java | 2 +- .../sonicether/soundphysics/SPGuiFactory.java | 11 ------- .../sonicether/soundphysics/SoundPhysics.java | 2 +- src/main/resources/mcmod.info | 4 +-- 6 files changed, 23 insertions(+), 34 deletions(-) diff --git a/build.gradle b/build.gradle index a49cc919..f4fa4125 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { 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" +version = "1.12.1" archivesBaseName = "Sound-Physics" jar { @@ -26,7 +26,7 @@ compileJava { } minecraft { - version = "1.12-14.21.0.2334" + version = "1.12.1-14.22.0.2452" runDir = "run" // the mappings can be changed at any time, and must be in the following format. @@ -34,7 +34,7 @@ minecraft { // stable_# stables are built at the discretion of the MCP team. // Use non-default mappings at your own risk. they may not always work. // simply re-run your setup task after changing the mappings to update your workspace. - mappings = "snapshot_20170617" + mappings = "snapshot_20170624" // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. } diff --git a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java index c3d43c2a..b675aec0 100644 --- a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java @@ -21,38 +21,38 @@ public class CoreModInjector implements IClassTransformer { @Override public byte[] transform(final String obfuscated, final String deobfuscated, byte[] bytes) { - if (obfuscated.equals("chk$a")) { + 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, "", "(Lchk;)V", Opcodes.INVOKESPECIAL, + bytes = patchMethodInClass(obfuscated, bytes, "", "(Lchm;)V", Opcodes.INVOKESPECIAL, AbstractInsnNode.METHOD_INSN, "", null, toInject, false, 0, 0, false, 0); } else - if (obfuscated.equals("chk")) { + 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", "(Lqe;)V", false)); + "setLastSoundCategory", "(Lqg;)V", false)); // Target method: playSound - bytes = patchMethodInClass(obfuscated, bytes, "c", "(Lcgr;)V", Opcodes.INVOKEVIRTUAL, + 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, "cgr", "a", "()Lnd;", true)); - toInject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "nd", "toString", "()Ljava/lang/String;", false)); + 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", "(Lcgr;)V", Opcodes.INVOKEVIRTUAL, + bytes = patchMethodInClass(obfuscated, bytes, "c", "(Lcgt;)V", Opcodes.INVOKEVIRTUAL, AbstractInsnNode.METHOD_INSN, "setVolume", null, toInject, false, 0, 0, false, 0); toInject = new InsnList(); @@ -60,9 +60,9 @@ public byte[] transform(final String obfuscated, final String deobfuscated, byte "globalVolumeMultiplier", "F")); toInject.add(new InsnNode(Opcodes.FMUL)); - // Target method: playSound - bytes = patchMethodInClass(obfuscated, bytes, "c", "(Lcgr;)V", Opcodes.INVOKESPECIAL, - AbstractInsnNode.METHOD_INSN, "e", "(Lcgr;)F", toInject, false, 0, 0, false, 0); + // 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")) { @@ -110,7 +110,7 @@ public byte[] transform(final String obfuscated, final String deobfuscated, byte AbstractInsnNode.METHOD_INSN, "", null, toInject, true, 0, 0, false, 0); } else - if (obfuscated.equals("pj")) { + if (obfuscated.equals("pl")) { // Inside PlayerList InsnList toInject = new InsnList(); @@ -121,24 +121,24 @@ public byte[] transform(final String obfuscated, final String deobfuscated, byte toInject.add(new InsnNode(Opcodes.DMUL)); // Target method: sendToAllNearExcept - bytes = patchMethodInClass(obfuscated, bytes, "a", "(Laeb;DDDDILht;)V", Opcodes.DCMPG, + bytes = patchMethodInClass(obfuscated, bytes, "a", "(Laed;DDDDILht;)V", Opcodes.DCMPG, AbstractInsnNode.INSN, "", "", toInject, true, 0, 0, false, 0); } else - if (obfuscated.equals("ve")) { + 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", "(Lve;Lqc;)D", false)); + "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", "(Lqc;FF)V", Opcodes.INVOKEVIRTUAL, + bytes = patchMethodInClass(obfuscated, bytes, "a", "(Lqe;FF)V", Opcodes.INVOKEVIRTUAL, AbstractInsnNode.METHOD_INSN, "bK", null, toInject, true, 0, 0, false, -3); } diff --git a/src/main/java/com/sonicether/soundphysics/CoreModLoader.java b/src/main/java/com/sonicether/soundphysics/CoreModLoader.java index faff1d41..72f21010 100644 --- a/src/main/java/com/sonicether/soundphysics/CoreModLoader.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModLoader.java @@ -5,7 +5,7 @@ import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.MCVersion; -@MCVersion(value = "1.12") +@MCVersion(value = "1.12.1") public class CoreModLoader implements IFMLLoadingPlugin { @Override diff --git a/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java b/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java index e508c7e0..2e105b82 100644 --- a/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java +++ b/src/main/java/com/sonicether/soundphysics/SPGuiFactory.java @@ -22,20 +22,9 @@ public GuiScreen createConfigGui(GuiScreen parentScreen) { return new SPGuiConfig(parentScreen); } - @Override - public Class mainConfigGuiClass() { - return SPGuiConfig.class; - } - @Override public Set runtimeGuiCategories() { return null; } - @SuppressWarnings("deprecation") - @Override - public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { - return null; - } - } diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 89295f62..a7f1287f 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -24,7 +24,7 @@ import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; -@Mod(modid = SoundPhysics.modid, version = SoundPhysics.version, guiFactory = "com.sonicether.soundphysics.SPGuiFactory") +@Mod(modid = SoundPhysics.modid, clientSideOnly = true, version = SoundPhysics.version, guiFactory = "com.sonicether.soundphysics.SPGuiFactory") public class SoundPhysics { public static final String modid = "soundphysics"; diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index cb9e737d..a9f32e50 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -4,8 +4,8 @@ "name": "Sound Physics", "description": "Provides realistic sound attenuation, reverberation, and absorption through blocks.", "version": "1.0.4", - "mcversion": "1.12", + "mcversion": "1.12.1", "url": "", - "authorList": ["Sonic Ether"] + "authorList": ["Sonic Ether","daipenger"] } ] From 090dcbfdbca2b1e97eb8508479adc64498717ed8 Mon Sep 17 00:00:00 2001 From: daipenger Date: Sat, 16 Sep 2017 14:24:01 +0200 Subject: [PATCH 32/39] Revert "Fix the pesky stereo sound files bug" This reverts commit d14442e89100999b88fc92d364f22b3d6a3f0bc9. --- src/main/java/com/sonicether/soundphysics/Config.java | 3 +++ .../java/com/sonicether/soundphysics/CoreModInjector.java | 7 ++++--- .../java/com/sonicether/soundphysics/ReverbParams.java | 8 ++++---- .../java/com/sonicether/soundphysics/SoundPhysics.java | 4 ++++ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/Config.java b/src/main/java/com/sonicether/soundphysics/Config.java index 4686f7cc..3335a7c8 100644 --- a/src/main/java/com/sonicether/soundphysics/Config.java +++ b/src/main/java/com/sonicether/soundphysics/Config.java @@ -17,6 +17,7 @@ public class Config { private Configuration forgeConfig; // 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; @@ -81,6 +82,8 @@ public List getConfigElements() { 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, diff --git a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java index b675aec0..bf3ae720 100644 --- a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java @@ -101,13 +101,14 @@ public byte[] transform(final String obfuscated, final String deobfuscated, byte InsnList toInject = new InsnList(); toInject.add(new FieldInsnNode(Opcodes.GETSTATIC, "com/sonicether/soundphysics/SoundPhysics", - "globalVolumeMultiplier", "F")); - toInject.add(new InsnNode(Opcodes.FMUL)); + "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, 0, 0, false, 0); + AbstractInsnNode.METHOD_INSN, "", null, toInject, true, 2, 0, false, 0); } else if (obfuscated.equals("pl")) { diff --git a/src/main/java/com/sonicether/soundphysics/ReverbParams.java b/src/main/java/com/sonicether/soundphysics/ReverbParams.java index 606cff9d..97f269f0 100644 --- a/src/main/java/com/sonicether/soundphysics/ReverbParams.java +++ b/src/main/java/com/sonicether/soundphysics/ReverbParams.java @@ -28,7 +28,7 @@ public static ReverbParams getReverb0() { r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.011f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.16f; + r.roomRolloffFactor = 0.16f * Config.rolloffFactor; return r; } @@ -46,7 +46,7 @@ public static ReverbParams getReverb1() { r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.011f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.15f; + r.roomRolloffFactor = 0.15f * Config.rolloffFactor; return r; } @@ -64,7 +64,7 @@ public static ReverbParams getReverb2() { r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.021f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.13f; + r.roomRolloffFactor = 0.13f * Config.rolloffFactor; return r; } @@ -82,7 +82,7 @@ public static ReverbParams getReverb3() { r.lateReverbGain = 1.26f; r.lateReverbDelay = 0.021f; r.airAbsorptionGainHF = 0.994f; - r.roomRolloffFactor = 0.11f; + r.roomRolloffFactor = 0.11f * Config.rolloffFactor; return r; } diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index a7f1287f..ae264aab 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -23,6 +23,7 @@ import net.minecraftforge.fml.common.Mod.Instance; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import paulscode.sound.SoundSystemConfig; @Mod(modid = SoundPhysics.modid, clientSideOnly = true, version = SoundPhysics.version, guiFactory = "com.sonicether.soundphysics.SPGuiFactory") public class SoundPhysics { @@ -70,6 +71,8 @@ public void init(final FMLInitializationEvent event) { // 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 = Config.rolloffFactor; public static float globalVolumeMultiplier = 4.0f; public static float globalReverbMultiplier = 0.7f * Config.globalReverbGain; public static double soundDistanceAllowance = Config.soundDistanceAllowance; @@ -84,6 +87,7 @@ public static void init() { } public static void applyConfigChanges() { + globalRolloffFactor = Config.rolloffFactor; globalReverbMultiplier = 0.7f * Config.globalReverbGain; soundDistanceAllowance = Config.soundDistanceAllowance; From bc4bb858270df1a7f57ea4860f43fc910d549e7f Mon Sep 17 00:00:00 2001 From: daipenger Date: Sat, 16 Sep 2017 14:39:50 +0200 Subject: [PATCH 33/39] Forge update --- build.gradle | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/build.gradle b/build.gradle index f4fa4125..2b0a44ae 100644 --- a/build.gradle +++ b/build.gradle @@ -26,40 +26,12 @@ compileJava { } minecraft { - version = "1.12.1-14.22.0.2452" + version = "1.12.1-14.22.1.2481" runDir = "run" - - // the mappings can be changed at any time, and must be in the following format. - // snapshot_YYYYMMDD snapshot are built nightly. - // stable_# stables are built at the discretion of the MCP team. - // Use non-default mappings at your own risk. they may not always work. - // simply re-run your setup task after changing the mappings to update your workspace. mappings = "snapshot_20170624" - // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. } dependencies { - // you may put jars on which you depend on in ./libs - // or you may define them like so.. - //compile "some.group:artifact:version:classifier" - //compile "some.group:artifact:version" - - // real examples - //compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env - //compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env - - // the 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. - //provided 'com.mod-buildcraft:buildcraft:6.0.8:dev' - - // the deobf configurations: 'deobfCompile' and 'deobfProvided' are the same as the normal compile and provided, - // except that these dependencies get remapped to your current MCP mappings - //deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev' - //deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev' - - // for more info... - // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html - } processResources { From 0c817bb9a000f0548f32e436c7496945e4c15589 Mon Sep 17 00:00:00 2001 From: daipenger Date: Sat, 16 Sep 2017 15:30:59 +0200 Subject: [PATCH 34/39] Remove redundant values, move stuff around --- .../com/sonicether/soundphysics/Config.java | 48 +++++++++++-------- .../soundphysics/CoreModLoader.java | 2 +- .../sonicether/soundphysics/SPGuiConfig.java | 2 +- .../sonicether/soundphysics/SoundPhysics.java | 16 ++----- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/Config.java b/src/main/java/com/sonicether/soundphysics/Config.java index 3335a7c8..acbfacf6 100644 --- a/src/main/java/com/sonicether/soundphysics/Config.java +++ b/src/main/java/com/sonicether/soundphysics/Config.java @@ -14,33 +14,34 @@ public class Config { + public static final Config instance; private Configuration forgeConfig; // 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; + 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 = true; - public static int environmentEvaluationRays = 32; - public static boolean simplerSharedAirspaceSimulation = false; + public static boolean skipRainOcclusionTracing; + public static int environmentEvaluationRays; + public static boolean simplerSharedAirspaceSimulation; // 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; + 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; // misc public static boolean debugLogging = false; @@ -53,6 +54,13 @@ public class Config { private static final String categoryMaterialProperties = "Material properties"; private static final String categoryMisc = "Misc"; + static { + instance = new Config(); + } + + private Config() { + } + public void preInit(final FMLPreInitializationEvent event) { this.forgeConfig = new Configuration(event.getSuggestedConfigurationFile()); syncConfig(); diff --git a/src/main/java/com/sonicether/soundphysics/CoreModLoader.java b/src/main/java/com/sonicether/soundphysics/CoreModLoader.java index 72f21010..0f2f40ec 100644 --- a/src/main/java/com/sonicether/soundphysics/CoreModLoader.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModLoader.java @@ -5,7 +5,7 @@ import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.MCVersion; -@MCVersion(value = "1.12.1") +@MCVersion(value = SoundPhysics.mcVersion) public class CoreModLoader implements IFMLLoadingPlugin { @Override diff --git a/src/main/java/com/sonicether/soundphysics/SPGuiConfig.java b/src/main/java/com/sonicether/soundphysics/SPGuiConfig.java index da53b926..58164a52 100644 --- a/src/main/java/com/sonicether/soundphysics/SPGuiConfig.java +++ b/src/main/java/com/sonicether/soundphysics/SPGuiConfig.java @@ -6,7 +6,7 @@ public class SPGuiConfig extends GuiConfig { public SPGuiConfig(final GuiScreen parent) { - super(parent, SoundPhysics.instance.config.getConfigElements(), SoundPhysics.modid, false, false, + super(parent, Config.instance.getConfigElements(), SoundPhysics.modid, false, false, "Sound Physics Configuration"); } diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index ae264aab..fca3bf58 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -20,33 +20,25 @@ import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.Mod.Instance; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import paulscode.sound.SoundSystemConfig; -@Mod(modid = SoundPhysics.modid, clientSideOnly = true, version = SoundPhysics.version, guiFactory = "com.sonicether.soundphysics.SPGuiFactory") +@Mod(modid = SoundPhysics.modid, clientSideOnly = true, acceptedMinecraftVersions = SoundPhysics.mcVersion, version = SoundPhysics.version, guiFactory = "com.sonicether.soundphysics.SPGuiFactory") public class SoundPhysics { public static final String modid = "soundphysics"; public static final String version = "1.0.4"; - @Instance(modid) - public static SoundPhysics instance; - - public final Config config; - - public SoundPhysics() { - this.config = new Config(); - } + public static final String mcVersion = "1.12.1"; @Mod.EventHandler public void preInit(final FMLPreInitializationEvent event) { - this.config.preInit(event); + Config.instance.preInit(event); } @Mod.EventHandler public void init(final FMLInitializationEvent event) { - this.config.init(event); + Config.instance.init(event); } private static final String logPrefix = "[SOUND PHYSICS]"; From 9538e558a14dd219d0f73292b8d044def3cf25c7 Mon Sep 17 00:00:00 2001 From: daipenger Date: Sat, 16 Sep 2017 15:39:05 +0200 Subject: [PATCH 35/39] Remove all logging I guess no one uses this anyways (and for testing purposes just revert this locally) So no one needs that extra branching --- .../com/sonicether/soundphysics/Config.java | 17 ------ .../soundphysics/CoreModInjector.java | 23 +------ .../sonicether/soundphysics/SoundPhysics.java | 61 ------------------- 3 files changed, 1 insertion(+), 100 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/Config.java b/src/main/java/com/sonicether/soundphysics/Config.java index acbfacf6..5a880d34 100644 --- a/src/main/java/com/sonicether/soundphysics/Config.java +++ b/src/main/java/com/sonicether/soundphysics/Config.java @@ -43,16 +43,9 @@ public class Config { public static float sandReflectivity; public static float snowReflectivity; - // misc - public static boolean debugLogging = false; - public static boolean occlusionLogging = false; - public static boolean environmentLogging = false; - public static boolean performanceLogging = false; - private static final String categoryGeneral = "General"; private static final String categoryPerformance = "Performance"; private static final String categoryMaterialProperties = "Material properties"; - private static final String categoryMisc = "Misc"; static { instance = new Config(); @@ -83,7 +76,6 @@ public List getConfigElements() { 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))); - list.add(new ConfigElement(this.forgeConfig.getCategory(Config.categoryMisc))); return list; } @@ -140,15 +132,6 @@ private void syncConfig() { snowReflectivity = this.forgeConfig.getFloat("Snow Reflectivity", categoryMaterialProperties, 0.2f, 0.0f, 1.0f, "Sound reflectivity for snow blocks."); - // misc - debugLogging = this.forgeConfig.getBoolean("Debug Logging", categoryMisc, false, "General debug logging"); - occlusionLogging = this.forgeConfig.getBoolean("Occlusion Logging", categoryMisc, false, - "Occlusion tracing information logging"); - environmentLogging = this.forgeConfig.getBoolean("Environment Logging", categoryMisc, false, - "Environment evaluation information logging"); - performanceLogging = this.forgeConfig.getBoolean("Performance Logging", categoryMisc, false, - "Performance information logging"); - 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 index bf3ae720..76153951 100644 --- a/src/main/java/com/sonicether/soundphysics/CoreModInjector.java +++ b/src/main/java/com/sonicether/soundphysics/CoreModInjector.java @@ -151,27 +151,19 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St final String targetInvocationMethodName, final String targetInvocationMethodSignature, final InsnList instructionsToInject, final boolean insertBefore, final int nodesToDeleteBefore, final int nodesToDeleteAfter, final boolean deleteTargetNode, final int targetNodeOffset) { - log("//// Patching Class: " + className); - // Setup ASM class manipulation stuff final ClassNode classNode = new ClassNode(); final 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 final Iterator methodIterator = classNode.methods.iterator(); + while (methodIterator.hasNext()) { final MethodNode m = methodIterator.next(); - log("@" + m.name + " " + m.desc); - // Check if this is the method name and the signature matches if (m.name.equals(targetMethod) && m.desc.equals(targetMethodSignature)) { - log("Inside target method: " + targetMethod); AbstractInsnNode targetNode = null; - // Loop over the instruction set final ListIterator nodeIterator = m.instructions.iterator(); while (nodeIterator.hasNext()) { AbstractInsnNode currentNode = nodeIterator.next(); @@ -184,8 +176,6 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St if (method.name.equals(targetInvocationMethodName)) { if (method.desc.equals(targetInvocationMethodSignature) || targetInvocationMethodSignature == null) { - log("Found target method invocation for injection: " - + targetInvocationMethodName); targetNode = currentNode; // Due to collisions, do not put break // statements here! @@ -195,7 +185,6 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St } } else { if (currentNode.getType() == targetNodeType) { - log("Found target node for injection: " + targetNodeOpcode); targetNode = currentNode; // Due to collisions, do not put break // statements here! @@ -224,13 +213,11 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St // If we've found the target, inject the instructions! for (int i = 0; i < nodesToDeleteBefore; i++) { final AbstractInsnNode previousNode = targetNode.getPrevious(); - log("Removing Node " + previousNode.getOpcode()); m.instructions.remove(previousNode); } for (int i = 0; i < nodesToDeleteAfter; i++) { final AbstractInsnNode nextNode = targetNode.getNext(); - log("Removing Node " + nextNode.getOpcode()); m.instructions.remove(nextNode); } @@ -248,17 +235,9 @@ private byte[] patchMethodInClass(String className, final byte[] bytes, final St } } - log("//// Class finished: " + className); - final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); classNode.accept(writer); return writer.toByteArray(); } - private void log(final String message) { - if (Config.debugLogging) { - SoundPhysics.log(message); - } - } - } diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index fca3bf58..a92deade 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -73,7 +73,6 @@ public void init(final FMLInitializationEvent event) { * CALLED BY ASM INJECTED CODE! */ public static void init() { - log("Initializing Sound Physics..."); setupEFX(); mc = Minecraft.getMinecraft(); } @@ -175,25 +174,7 @@ public static void setLastSoundName(final String name) { * CALLED BY ASM INJECTED CODE! */ public static void onPlaySound(final float posX, final float posY, final float posZ, final int sourceID) { - if (Config.debugLogging) { - logGeneral("onPlaySound, Source ID: " + sourceID + " " + posX + ", " + posY + ", " + posZ - + " Sound category: " + lastSoundCategory.toString() + " Sound name: " + lastSoundName); - } - - long startTime = 0; - long endTime = 0; - - if (Config.performanceLogging) { - startTime = System.nanoTime(); - } - evaluateEnvironment(sourceID, posX, posY, posZ); - - if (Config.performanceLogging) { - endTime = System.nanoTime(); - log("Total calculation time for sound " + lastSoundName + ": " - + (double) (endTime - startTime) / (double) 1000000 + " milliseconds"); - } } /** @@ -319,12 +300,6 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi final Vec3d soundPos = offsetSoundByName(posX, posY, posZ, playerPos, lastSoundName, lastSoundCategory); final Vec3d normalToPlayer = playerPos.subtract(soundPos).normalize(); - if (Config.debugLogging) { - logGeneral("Player pos: " + playerPos.x + ", " + playerPos.y + ", " + playerPos.z + " Sound Pos: " - + soundPos.x + ", " + soundPos.y + ", " + soundPos.z + " To player vector: " - + normalToPlayer.x + ", " + normalToPlayer.y + ", " + normalToPlayer.z); - } - Vec3d rayOrigin = soundPos; float occlusionAccumulation = 0.0f; @@ -345,28 +320,15 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi blockOcclusion *= 0.15f; } - if (Config.occlusionLogging) { - logOcclusion(blockHit.getUnlocalizedName() + " " + rayHit.hitVec.x + ", " + rayHit.hitVec.y + ", " - + rayHit.hitVec.z); - } - 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); - - if (Config.occlusionLogging) { - logOcclusion("New trace position: " + rayOrigin.x + ", " + rayOrigin.y + ", " + rayOrigin.z); - } } directCutoff = (float) Math.exp(-occlusionAccumulation * absorptionCoeff); float directGain = (float) Math.pow(directCutoff, 0.1); - if (Config.occlusionLogging) { - logOcclusion("direct cutoff: " + directCutoff + " direct gain:" + directGain); - } - // Calculate reverb parameters for this sound float sendGain0 = 0.0f; float sendGain1 = 0.0f; @@ -534,12 +496,6 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi directGain = (float) Math.pow(directCutoff, 0.1); - if (Config.environmentLogging) { - logEnvironment("Bounce reflectivity 0: " + bounceReflectivityRatio[0] + " bounce reflectivity 1: " - + bounceReflectivityRatio[1] + " bounce reflectivity 2: " + bounceReflectivityRatio[2] - + " bounce reflectivity 3: " + bounceReflectivityRatio[3]); - } - sendGain1 *= bounceReflectivityRatio[1]; sendGain2 *= (float) Math.pow(bounceReflectivityRatio[2], 3.0); sendGain3 *= (float) Math.pow(bounceReflectivityRatio[3], 4.0); @@ -554,11 +510,6 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi sendGain2 *= (float) Math.pow(sendCutoff2, 0.1); sendGain3 *= (float) Math.pow(sendCutoff3, 0.1); - if (Config.environmentLogging) { - logEnvironment("Final environment settings: " + sendGain0 + ", " + sendGain1 + ", " + sendGain2 - + ", " + sendGain3); - } - if (mc.player.isInWater()) { sendCutoff0 *= 0.4f; sendCutoff1 *= 0.4f; @@ -644,18 +595,6 @@ public static void log(final String message) { System.out.println(logPrefix.concat(" : ").concat(message)); } - public static void logOcclusion(final String message) { - System.out.println(logPrefix.concat(" [OCCLUSION] : ").concat(message)); - } - - public static void logEnvironment(final String message) { - System.out.println(logPrefix.concat(" [ENVIRONMENT] : ").concat(message)); - } - - public static void logGeneral(final String message) { - System.out.println(logPrefix.concat(": ").concat(message)); - } - public static void logError(final String errorMessage) { System.out.println(logPrefix.concat(" [ERROR]: ").concat(errorMessage)); } From ab8fec21a58c4fbc1979b7149062e242fbb45c13 Mon Sep 17 00:00:00 2001 From: daipenger Date: Sat, 16 Sep 2017 16:30:20 +0200 Subject: [PATCH 36/39] Altering default material absorption values --- .../java/com/sonicether/soundphysics/Config.java | 10 +++++----- .../sonicether/soundphysics/SoundPhysics.java | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/Config.java b/src/main/java/com/sonicether/soundphysics/Config.java index 5a880d34..045043ae 100644 --- a/src/main/java/com/sonicether/soundphysics/Config.java +++ b/src/main/java/com/sonicether/soundphysics/Config.java @@ -113,19 +113,19 @@ private void syncConfig() { "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, 1.0f, 0.0f, + 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.4f, 0.0f, 1.0f, + 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.5f, 0.0f, + 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, 1.0f, 0.0f, + 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.05f, 0.0f, + 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."); diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index a92deade..7b7e8c98 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -229,12 +229,11 @@ private static Vec3d getNormalFromFacing(final EnumFacing sideHit) { } private static Vec3d reflect(final Vec3d dir, final Vec3d normal) { - // dir - 2.0 * dot(normal, dir) * normal - final double dot = dir.dotProduct(normal); + final double dot2 = dir.dotProduct(normal) * 2; - final double x = dir.x - 2.0 * dot * normal.x; - final double y = dir.y - 2.0 * dot * normal.y; - final double z = dir.z - 2.0 * dot * normal.z; + 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); } @@ -254,7 +253,7 @@ private static Vec3d offsetSoundByName(final double soundX, final double soundY, offsetY = 0.1; } - if (category == SoundCategory.BLOCKS || category == SoundCategory.RECORDS || name.matches(".*block.*")) { + if (category == SoundCategory.BLOCKS || name.matches(".*block.*")) { // The ray will probably hit the block that it's emitting from // before // escaping. Offset the ray start position towards the player by the @@ -279,8 +278,9 @@ private static Vec3d offsetSoundByName(final double soundX, final double soundY, @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) { - // Menu clicks, posY <= 0 as a condition has to be there: Ingame + 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; From 1aafd1acecee040cf59790cc4c1e6b1b5b4a35c6 Mon Sep 17 00:00:00 2001 From: daipenger Date: Sun, 17 Sep 2017 17:35:56 +0200 Subject: [PATCH 37/39] Precompile regex patterns --- .../com/sonicether/soundphysics/SoundPhysics.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 7b7e8c98..79addb4c 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -1,5 +1,7 @@ package com.sonicether.soundphysics; +import java.util.regex.Pattern; + import org.lwjgl.openal.AL10; import org.lwjgl.openal.AL11; import org.lwjgl.openal.ALC10; @@ -31,6 +33,10 @@ public class SoundPhysics { public static final String version = "1.0.4"; public static final String mcVersion = "1.12.1"; + 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); @@ -90,7 +96,6 @@ public static void applyConfigChanges() { setReverbParams(ReverbParams.getReverb2(), auxFXSlot2, reverb2); setReverbParams(ReverbParams.getReverb3(), auxFXSlot3, reverb3); } - } private static void setupEFX() { @@ -181,7 +186,7 @@ public static void onPlaySound(final float posX, final float posY, final float p * CALLED BY ASM INJECTED CODE! */ public static double calculateEntitySoundOffset(final Entity entity, final SoundEvent sound) { - if (sound.getSoundName().getResourcePath().matches(".*step.*")) { + if (stepPattern.matcher(sound.getSoundName().getResourcePath()).matches()) { return 0; } @@ -249,11 +254,11 @@ private static Vec3d offsetSoundByName(final double soundX, final double soundY, double tempNormY = 0; double tempNormZ = 0; - if (soundY % 1.0 < 0.001 || name.matches(".*step.*")) { + if (soundY % 1.0 < 0.001 || stepPattern.matcher(name).matches()) { offsetY = 0.1; } - if (category == SoundCategory.BLOCKS || name.matches(".*block.*")) { + 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 @@ -286,7 +291,7 @@ private static void evaluateEnvironment(final int sourceID, final float posX, fi return; } - final boolean isRain = 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); From 6d0037e5a2ab221ee1e77ddcba55e5c1c8a793b0 Mon Sep 17 00:00:00 2001 From: daipenger Date: Tue, 14 Nov 2017 21:44:50 +0100 Subject: [PATCH 38/39] 1.12.2 --- build.gradle | 6 +++--- src/main/java/com/sonicether/soundphysics/SoundPhysics.java | 2 +- src/main/resources/mcmod.info | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 2b0a44ae..b51e22bf 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { 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.1" +version = "1.12.2" archivesBaseName = "Sound-Physics" jar { @@ -26,9 +26,9 @@ compileJava { } minecraft { - version = "1.12.1-14.22.1.2481" + version = "1.12.2-14.23.0.2542" runDir = "run" - mappings = "snapshot_20170624" + mappings = "snapshot_20171003" } dependencies { diff --git a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java index 79addb4c..57a41b1b 100644 --- a/src/main/java/com/sonicether/soundphysics/SoundPhysics.java +++ b/src/main/java/com/sonicether/soundphysics/SoundPhysics.java @@ -31,7 +31,7 @@ public class SoundPhysics { public static final String modid = "soundphysics"; public static final String version = "1.0.4"; - public static final String mcVersion = "1.12.1"; + public static final String mcVersion = "1.12.2"; private static final Pattern rainPattern = Pattern.compile(".*rain.*"); private static final Pattern stepPattern = Pattern.compile(".*step.*"); diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index a9f32e50..8241d747 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -4,7 +4,7 @@ "name": "Sound Physics", "description": "Provides realistic sound attenuation, reverberation, and absorption through blocks.", "version": "1.0.4", - "mcversion": "1.12.1", + "mcversion": "1.12.2", "url": "", "authorList": ["Sonic Ether","daipenger"] } From 0161754307e84b736023d7cdd78208369294f622 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 9 May 2019 21:34:56 +0200 Subject: [PATCH 39/39] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c04ef39b..dce1c21d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ # Sound-Physics A Minecraft mod that provides realistic sound attenuation, reverberation, and absorption through blocks. -This is a fork! TODO: There is still some cleanup left! Sonic Ether's original source code was very messy! \ No newline at end of file +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!