From eaeedbaadb513cc3b2cf05430cdc0aca02a3ee34 Mon Sep 17 00:00:00 2001 From: Ian William O'Neill Date: Thu, 11 Jul 2019 05:43:51 +0100 Subject: [PATCH] Slayer Points command and some Renaming. (#966) * Renaming and Tests for Sound Effects in cache. * SlayerPlugin: added !points command. --- .../sound/AudioEnvelopeLoader.java} | 59 +-- .../loaders/sound/InstrumentLoader.java | 93 +++++ .../loaders/sound/SoundEffect1Loader.java | 93 ----- .../loaders/sound/SoundEffect3Loader.java | 95 ----- .../loaders/sound/SoundEffectLoader.java | 67 +++- ...oader.java => SoundEffectTrackLoader.java} | 46 +-- ...tion.java => AudioEnvelopeDefinition.java} | 60 ++- .../sound/InstrumentDefinition.java | 356 ++++++++++++++++++ .../sound/SoundEffectDefinition.java | 103 ++++- ...n.java => SoundEffectTrackDefinition.java} | 72 +++- .../cache/SoundEffectsDumperTest.java | 78 +++- runelite-client/pom.xml | 24 +- .../client/plugins/PluginWatcher.java | 2 +- .../client/plugins/config/ConfigPlugin.java | 22 +- .../client/plugins/slayer/SlayerConfig.java | 11 + .../client/plugins/slayer/SlayerPlugin.java | 45 +++ 16 files changed, 927 insertions(+), 299 deletions(-) rename cache/src/main/java/net/runelite/cache/definitions/{sound/SoundEffect1Definition.java => loaders/sound/AudioEnvelopeLoader.java} (57%) create mode 100644 cache/src/main/java/net/runelite/cache/definitions/loaders/sound/InstrumentLoader.java delete mode 100644 cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffect1Loader.java delete mode 100644 cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffect3Loader.java rename cache/src/main/java/net/runelite/cache/definitions/loaders/sound/{SoundEffect2Loader.java => SoundEffectTrackLoader.java} (63%) rename cache/src/main/java/net/runelite/cache/definitions/sound/{SoundEffect3Definition.java => AudioEnvelopeDefinition.java} (56%) create mode 100644 cache/src/main/java/net/runelite/cache/definitions/sound/InstrumentDefinition.java rename cache/src/main/java/net/runelite/cache/definitions/sound/{SoundEffect2Definition.java => SoundEffectTrackDefinition.java} (56%) diff --git a/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffect1Definition.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/AudioEnvelopeLoader.java similarity index 57% rename from cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffect1Definition.java rename to cache/src/main/java/net/runelite/cache/definitions/loaders/sound/AudioEnvelopeLoader.java index ecd9854892..084a8a9a86 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffect1Definition.java +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/AudioEnvelopeLoader.java @@ -22,34 +22,41 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package net.runelite.cache.definitions.sound; +package net.runelite.cache.definitions.loaders.sound; -public class SoundEffect1Definition +import net.runelite.cache.definitions.sound.AudioEnvelopeDefinition; +import net.runelite.cache.io.InputStream; + +public class AudioEnvelopeLoader { - public SoundEffect2Definition field1173; - public SoundEffect2Definition field1174; - public SoundEffect2Definition field1175; - public int field1176 = 500; - public int[] field1177 = new int[] + public AudioEnvelopeDefinition load(InputStream in) { - 0, 0, 0, 0, 0 - }; - public SoundEffect2Definition field1178; - public int[] field1179 = new int[] + AudioEnvelopeDefinition audioEnvelope = new AudioEnvelopeDefinition(); + + load(audioEnvelope, in); + + return audioEnvelope; + } + + private void load(AudioEnvelopeDefinition audioEnvelope, InputStream in) { - 0, 0, 0, 0, 0 - }; - public int[] field1180 = new int[] + audioEnvelope.form = in.readUnsignedByte(); + audioEnvelope.start = in.readInt(); + audioEnvelope.end = in.readInt(); + this.loadSegments(audioEnvelope, in); + } + + final void loadSegments(AudioEnvelopeDefinition audioEnvelope, InputStream in) { - 0, 0, 0, 0, 0 - }; - public SoundEffect2Definition field1181; - public SoundEffect3Definition field1182; - public SoundEffect2Definition field1183; - public int field1184 = 100; - public SoundEffect2Definition field1186; - public int field1187 = 0; - public int field1188 = 0; - public SoundEffect2Definition field1192; - public SoundEffect2Definition field1193; -} + audioEnvelope.segments = in.readUnsignedByte(); + audioEnvelope.durations = new int[audioEnvelope.segments]; + audioEnvelope.phases = new int[audioEnvelope.segments]; + + for (int i = 0; i < audioEnvelope.segments; ++i) + { + audioEnvelope.durations[i] = in.readUnsignedShort(); + audioEnvelope.phases[i] = in.readUnsignedShort(); + } + + } +} \ No newline at end of file diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/InstrumentLoader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/InstrumentLoader.java new file mode 100644 index 0000000000..f3d2326760 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/InstrumentLoader.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders.sound; + +import net.runelite.cache.definitions.sound.InstrumentDefinition; +import net.runelite.cache.definitions.sound.AudioEnvelopeDefinition; +import net.runelite.cache.io.InputStream; + +public class InstrumentLoader +{ + private final AudioEnvelopeLoader aeLoader = new AudioEnvelopeLoader(); + private final SoundEffectLoader seLoader = new SoundEffectLoader(); + + public InstrumentDefinition load(InputStream in) + { + InstrumentDefinition instrument = new InstrumentDefinition(); + + load(instrument, in); + + return instrument; + } + + private void load(InstrumentDefinition instrument, InputStream in) + { + instrument.pitch = aeLoader.load(in); + instrument.volume = aeLoader.load(in); + int volume = in.readUnsignedByte(); + if (volume != 0) + { + in.setOffset(in.getOffset() - 1); + instrument.pitchModifier = aeLoader.load(in); + instrument.pitchModifierAmplitude = aeLoader.load(in); + } + + volume = in.readUnsignedByte(); + if (volume != 0) + { + in.setOffset(in.getOffset() - 1); + instrument.volumeMultiplier = aeLoader.load(in); + instrument.volumeMultiplierAmplitude = aeLoader.load(in); + } + + volume = in.readUnsignedByte(); + if (volume != 0) + { + in.setOffset(in.getOffset() - 1); + instrument.release = aeLoader.load(in); + instrument.field1175 = aeLoader.load(in); + } + + for (int i = 0; i < 10; ++i) + { + int vol = in.readUnsignedShortSmart(); + if (vol == 0) + { + break; + } + + instrument.oscillatorVolume[i] = vol; + instrument.oscillatorPitch[i] = in.readShortSmart(); + instrument.oscillatorDelays[i] = in.readUnsignedShortSmart(); + } + + instrument.delayTime = in.readUnsignedShortSmart(); + instrument.delayDecay = in.readUnsignedShortSmart(); + instrument.duration = in.readUnsignedShort(); + instrument.offset = in.readUnsignedShort(); + instrument.filterEnvelope = new AudioEnvelopeDefinition(); + instrument.filter = seLoader.load(in, instrument.filterEnvelope); + } +} \ No newline at end of file diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffect1Loader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffect1Loader.java deleted file mode 100644 index a5c8f16f78..0000000000 --- a/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffect1Loader.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.cache.definitions.loaders.sound; - -import net.runelite.cache.definitions.sound.SoundEffect1Definition; -import net.runelite.cache.definitions.sound.SoundEffect2Definition; -import net.runelite.cache.io.InputStream; - -public class SoundEffect1Loader -{ - private final SoundEffect2Loader se2Loader = new SoundEffect2Loader(); - private final SoundEffect3Loader se3Loader = new SoundEffect3Loader(); - - public SoundEffect1Definition load(InputStream in) - { - SoundEffect1Definition se = new SoundEffect1Definition(); - - load(se, in); - - return se; - } - - private void load(SoundEffect1Definition se, InputStream var1) - { - se.field1181 = se2Loader.load(var1); - se.field1173 = se2Loader.load(var1); - int var2 = var1.readUnsignedByte(); - if (var2 != 0) - { - var1.setOffset(var1.getOffset() - 1); - se.field1174 = se2Loader.load(var1); - se.field1193 = se2Loader.load(var1); - } - - var2 = var1.readUnsignedByte(); - if (var2 != 0) - { - var1.setOffset(var1.getOffset() - 1); - se.field1183 = se2Loader.load(var1); - se.field1192 = se2Loader.load(var1); - } - - var2 = var1.readUnsignedByte(); - if (var2 != 0) - { - var1.setOffset(var1.getOffset() - 1); - se.field1178 = se2Loader.load(var1); - se.field1175 = se2Loader.load(var1); - } - - for (int var3 = 0; var3 < 10; ++var3) - { - int var4 = var1.readUnsignedShortSmart(); - if (var4 == 0) - { - break; - } - - se.field1180[var3] = var4; - se.field1179[var3] = var1.readShortSmart(); - se.field1177[var3] = var1.readUnsignedShortSmart(); - } - - se.field1187 = var1.readUnsignedShortSmart(); - se.field1184 = var1.readUnsignedShortSmart(); - se.field1176 = var1.readUnsignedShort(); - se.field1188 = var1.readUnsignedShort(); - se.field1186 = new SoundEffect2Definition(); - se.field1182 = se3Loader.load(var1, se.field1186); - } -} diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffect3Loader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffect3Loader.java deleted file mode 100644 index ad7f733efb..0000000000 --- a/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffect3Loader.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2017, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.cache.definitions.loaders.sound; - -import net.runelite.cache.definitions.sound.SoundEffect2Definition; -import net.runelite.cache.definitions.sound.SoundEffect3Definition; -import net.runelite.cache.io.InputStream; - -public class SoundEffect3Loader -{ - private final SoundEffect2Loader se2Loader = new SoundEffect2Loader(); - - public SoundEffect3Definition load(InputStream in, SoundEffect2Definition var2) - { - SoundEffect3Definition se = new SoundEffect3Definition(); - - load(se, in, var2); - - return se; - } - - private void load(SoundEffect3Definition se, InputStream var1, SoundEffect2Definition var2) - { - int var3 = var1.readUnsignedByte(); - se.field1155[0] = var3 >> 4; - se.field1155[1] = var3 & 15; - if (var3 != 0) - { - se.field1156[0] = var1.readUnsignedShort(); - se.field1156[1] = var1.readUnsignedShort(); - int var4 = var1.readUnsignedByte(); - - int var5; - int var6; - for (var5 = 0; var5 < 2; ++var5) - { - for (var6 = 0; var6 < se.field1155[var5]; ++var6) - { - se.field1154[var5][0][var6] = var1.readUnsignedShort(); - se.field1159[var5][0][var6] = var1.readUnsignedShort(); - } - } - - for (var5 = 0; var5 < 2; ++var5) - { - for (var6 = 0; var6 < se.field1155[var5]; ++var6) - { - if ((var4 & 1 << var5 * 4 << var6) != 0) - { - se.field1154[var5][1][var6] = var1.readUnsignedShort(); - se.field1159[var5][1][var6] = var1.readUnsignedShort(); - } - else - { - se.field1154[var5][1][var6] = se.field1154[var5][0][var6]; - se.field1159[var5][1][var6] = se.field1159[var5][0][var6]; - } - } - } - - if (var4 != 0 || se.field1156[1] != se.field1156[0]) - { - se2Loader.method1144(var2, var1); - } - } - else - { - int[] var7 = se.field1156; - se.field1156[1] = 0; - var7[0] = 0; - } - } -} diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectLoader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectLoader.java index ddb6a4d9fc..2ee518d4ee 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectLoader.java +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectLoader.java @@ -24,39 +24,70 @@ */ package net.runelite.cache.definitions.loaders.sound; +import net.runelite.cache.definitions.sound.AudioEnvelopeDefinition; import net.runelite.cache.definitions.sound.SoundEffectDefinition; -import net.runelite.cache.definitions.sound.SoundEffect1Definition; import net.runelite.cache.io.InputStream; public class SoundEffectLoader { - public SoundEffectDefinition load(byte[] b) + private final AudioEnvelopeLoader audioEnvelopeLoader = new AudioEnvelopeLoader(); + + public SoundEffectDefinition load(InputStream in, AudioEnvelopeDefinition audioEnvelope) { - SoundEffectDefinition se = new SoundEffectDefinition(); - InputStream in = new InputStream(b); + SoundEffectDefinition soundEffect = new SoundEffectDefinition(); - load(se, in); + load(soundEffect, audioEnvelope, in); - return se; + return soundEffect; } - private void load(SoundEffectDefinition se, InputStream var1) + private void load(SoundEffectDefinition soundEffect, AudioEnvelopeDefinition audioEnvelope, InputStream in) { - for (int var2 = 0; var2 < 10; ++var2) + int id = in.readUnsignedByte(); + soundEffect.pairs[0] = id >> 4; + soundEffect.pairs[1] = id & 15; + if (id != 0) { - int var3 = var1.readUnsignedByte(); - if (var3 != 0) + soundEffect.unity[0] = in.readUnsignedShort(); + soundEffect.unity[1] = in.readUnsignedShort(); + int track = in.readUnsignedByte(); + + for (int i = 0; i < 2; ++i) { - var1.setOffset(var1.getOffset() - 1); + for (int j = 0; j < soundEffect.pairs[i]; ++j) + { + soundEffect.phases[i][0][j] = in.readUnsignedShort(); + soundEffect.magnitudes[i][0][j] = in.readUnsignedShort(); + } + } - SoundEffect1Loader se1Loader = new SoundEffect1Loader(); - SoundEffect1Definition se1 = se1Loader.load(var1); + for (int i = 0; i < 2; ++i) + { + for (int j = 0; j < soundEffect.pairs[i]; ++j) + { + if ((track & 1 << i * 4 << j) != 0) + { + soundEffect.phases[i][1][j] = in.readUnsignedShort(); + soundEffect.magnitudes[i][1][j] = in.readUnsignedShort(); + } + else + { + soundEffect.phases[i][1][j] = soundEffect.phases[i][0][j]; + soundEffect.magnitudes[i][1][j] = soundEffect.magnitudes[i][0][j]; + } + } + } - se.field1008[var2] = se1; + if (track != 0 || soundEffect.unity[1] != soundEffect.unity[0]) + { + audioEnvelopeLoader.loadSegments(audioEnvelope, in); } } - - se.field1006 = var1.readUnsignedShort(); - se.field1009 = var1.readUnsignedShort(); + else + { + int[] clean = soundEffect.unity; + soundEffect.unity[1] = 0; + clean[0] = 0; + } } -} +} \ No newline at end of file diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffect2Loader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectTrackLoader.java similarity index 63% rename from cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffect2Loader.java rename to cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectTrackLoader.java index d9ae3d3abb..3b991fdc70 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffect2Loader.java +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/sound/SoundEffectTrackLoader.java @@ -24,39 +24,39 @@ */ package net.runelite.cache.definitions.loaders.sound; -import net.runelite.cache.definitions.sound.SoundEffect2Definition; +import net.runelite.cache.definitions.sound.SoundEffectTrackDefinition; +import net.runelite.cache.definitions.sound.InstrumentDefinition; import net.runelite.cache.io.InputStream; -public class SoundEffect2Loader +public class SoundEffectTrackLoader { - public SoundEffect2Definition load(InputStream in) + public SoundEffectTrackDefinition load(byte[] b) { - SoundEffect2Definition se = new SoundEffect2Definition(); + SoundEffectTrackDefinition soundEffect = new SoundEffectTrackDefinition(); + InputStream in = new InputStream(b); - load(se, in); + load(soundEffect, in); - return se; + return soundEffect; } - private void load(SoundEffect2Definition se, InputStream var1) + private void load(SoundEffectTrackDefinition soundEffect, InputStream in) { - se.field1087 = var1.readUnsignedByte(); - se.field1088 = var1.readInt(); - se.field1089 = var1.readInt(); - this.method1144(se, var1); - } - - final void method1144(SoundEffect2Definition se, InputStream var1) - { - se.field1092 = var1.readUnsignedByte(); - se.field1086 = new int[se.field1092]; - se.field1090 = new int[se.field1092]; - - for (int var2 = 0; var2 < se.field1092; ++var2) + for (int i = 0; i < 10; ++i) { - se.field1086[var2] = var1.readUnsignedShort(); - se.field1090[var2] = var1.readUnsignedShort(); + int volume = in.readUnsignedByte(); + if (volume != 0) + { + in.setOffset(in.getOffset() - 1); + + InstrumentLoader instrumentLoader = new InstrumentLoader(); + InstrumentDefinition instrument = instrumentLoader.load(in); + + soundEffect.instruments[i] = instrument; + } } + soundEffect.start = in.readUnsignedShort(); + soundEffect.end = in.readUnsignedShort(); } -} +} \ No newline at end of file diff --git a/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffect3Definition.java b/cache/src/main/java/net/runelite/cache/definitions/sound/AudioEnvelopeDefinition.java similarity index 56% rename from cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffect3Definition.java rename to cache/src/main/java/net/runelite/cache/definitions/sound/AudioEnvelopeDefinition.java index a6580c046f..46d709f6a4 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffect3Definition.java +++ b/cache/src/main/java/net/runelite/cache/definitions/sound/AudioEnvelopeDefinition.java @@ -24,10 +24,58 @@ */ package net.runelite.cache.definitions.sound; -public class SoundEffect3Definition +public class AudioEnvelopeDefinition { - public int[][][] field1154 = new int[2][2][4]; - public int[] field1155 = new int[2]; - public int[] field1156 = new int[2]; - public int[][][] field1159 = new int[2][2][4]; -} + public int segments = 2; + public int[] durations = new int[2]; + public int[] phases = new int[2]; + public int start; + public int end; + public int form; + public int ticks; + public int phaseIndex; + public int step; + public int amplitude; + public int max; + + public AudioEnvelopeDefinition() + { + this.durations[0] = 0; + this.durations[1] = '\uffff'; + this.phases[0] = 0; + this.phases[1] = '\uffff'; + } + + public final int step(int var1) + { + if (this.max >= this.ticks) + { + this.amplitude = this.phases[this.phaseIndex++] << 15; + + if (this.phaseIndex >= this.segments) + { + this.phaseIndex = this.segments - 1; + } + + this.ticks = (int) ((double) this.durations[this.phaseIndex] / 65536.0 * (double) var1); + + if (this.ticks > this.max) + { + this.step = ((this.phases[this.phaseIndex] << 15) - this.amplitude) / (this.ticks - this.max); + } + } + this.amplitude += this.step; + ++this.max; + + return this.amplitude - this.step >> 15; + } + + public final void reset() + { + this.ticks = 0; + this.phaseIndex = 0; + this.step = 0; + this.amplitude = 0; + this.max = 0; + } +} \ No newline at end of file diff --git a/cache/src/main/java/net/runelite/cache/definitions/sound/InstrumentDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/sound/InstrumentDefinition.java new file mode 100644 index 0000000000..fafaa7b8f8 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/sound/InstrumentDefinition.java @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.sound; + +import java.util.Random; + +public class InstrumentDefinition +{ + public AudioEnvelopeDefinition volume; + public AudioEnvelopeDefinition pitchModifier; + public AudioEnvelopeDefinition field1175; + public AudioEnvelopeDefinition release; + public AudioEnvelopeDefinition volumeMultiplier; + public AudioEnvelopeDefinition volumeMultiplierAmplitude; + public AudioEnvelopeDefinition pitchModifierAmplitude; + public AudioEnvelopeDefinition pitch; + + public int[] oscillatorDelays = new int[] + { + 0, 0, 0, 0, 0 + }; + public int[] oscillatorPitch = new int[] + { + 0, 0, 0, 0, 0 + }; + public int[] oscillatorVolume = new int[] + { + 0, 0, 0, 0, 0 + }; + + public SoundEffectDefinition filter; + public AudioEnvelopeDefinition filterEnvelope; + + static int[] samples = new int[220500]; + + static int[] NOISE = new int[32768]; + static int[] AUDIO_SINE = new int[32768]; + + static int[] phases = new int[5]; + static int[] delays = new int[5]; + + static int[] volumeSteps = new int[5]; + static int[] pitchSteps = new int[5]; + static int[] pitchBaseSteps = new int[5]; + + public int duration = 500; + public int delayDecay = 100; + public int delayTime = 0; + public int offset = 0; + + static + { + Random random = new Random(0); + + for (int i = 0; i < 32768; ++i) + { + InstrumentDefinition.NOISE[i] = (random.nextInt() & 2) - 1; + InstrumentDefinition.AUDIO_SINE[i] = (int) (Math.sin((double) i / 5215.1903) * 16384.0); + } + } + + public final int[] synthesize(int var1, int var2) + { + int var16; + int var15; + int var14; + int var11; + int var12; + int var13; + + InstrumentDefinition.method3854(samples, 0, var1); + + if (var2 < 10) + { + return samples; + } + + double var3 = (double) var1 / ((double) var2 + 0.0); + + this.pitch.reset(); + this.volume.reset(); + + int var5 = 0; + int var6 = 0; + int var7 = 0; + + if (this.pitchModifier != null) + { + this.pitchModifier.reset(); + this.pitchModifierAmplitude.reset(); + + var5 = (int) ((double) (this.pitchModifier.end - this.pitchModifier.start) * 32.768 / var3); + var6 = (int) ((double) this.pitchModifier.start * 32.768 / var3); + } + + int var8 = 0; + int var9 = 0; + int var10 = 0; + + if (this.volumeMultiplier != null) + { + this.volumeMultiplier.reset(); + this.volumeMultiplierAmplitude.reset(); + + var8 = (int) ((double) (this.volumeMultiplier.end - this.volumeMultiplier.start) * 32.768 / var3); + var9 = (int) ((double) this.volumeMultiplier.start * 32.768 / var3); + } + + for (var11 = 0; var11 < 5; ++var11) + { + if (this.oscillatorVolume[var11] == 0) + { + continue; + } + + InstrumentDefinition.phases[var11] = 0; + InstrumentDefinition.delays[var11] = (int) ((double) this.oscillatorDelays[var11] * var3); + InstrumentDefinition.volumeSteps[var11] = (this.oscillatorVolume[var11] << 14) / 100; + InstrumentDefinition.pitchSteps[var11] = (int) ((double) (this.pitch.end - this.pitch.start) * 32.768 * Math.pow(1.0057929410678534, this.oscillatorPitch[var11]) / var3); + InstrumentDefinition.pitchBaseSteps[var11] = (int) ((double) this.pitch.start * 32.768 / var3); + } + + for (var11 = 0; var11 < var1; ++var11) + { + var12 = this.pitch.step(var1); + var13 = this.volume.step(var1); + + if (this.pitchModifier != null) + { + var14 = this.pitchModifier.step(var1); + var15 = this.pitchModifierAmplitude.step(var1); + var12 += this.evaluateWave(var7, var15, this.pitchModifier.form) >> 1; + var7 = var7 + var6 + (var14 * var5 >> 16); + } + + if (this.volumeMultiplier != null) + { + var14 = this.volumeMultiplier.step(var1); + var15 = this.volumeMultiplierAmplitude.step(var1); + var13 = var13 * ((this.evaluateWave(var10, var15, this.volumeMultiplier.form) >> 1) + 32768) >> 15; + var10 = var10 + var9 + (var14 * var8 >> 16); + } + + for (var14 = 0; var14 < 5; ++var14) + { + if (this.oscillatorVolume[var14] == 0 || (var15 = delays[var14] + var11) >= var1) + { + continue; + } + + int[] arrn = samples; + int n = var15; + arrn[n] = arrn[n] + this.evaluateWave(phases[var14], var13 * volumeSteps[var14] >> 15, this.pitch.form); + int[] arrn2 = phases; + int n2 = var14; + arrn2[n2] = arrn2[n2] + ((var12 * pitchSteps[var14] >> 16) + pitchBaseSteps[var14]); + } + } + + if (this.release != null) + { + this.release.reset(); + this.field1175.reset(); + + var11 = 0; + boolean var20 = true; + + for (var14 = 0; var14 < var1; ++var14) + { + var15 = this.release.step(var1); + var16 = this.field1175.step(var1); + var12 = var20 ? (var15 * (this.release.end - this.release.start) >> 8) + this.release.start : (var16 * (this.release.end - this.release.start) >> 8) + this.release.start; + if ((var11 += 256) >= var12) + { + var11 = 0; + } + if (!var20) + { + continue; + } + InstrumentDefinition.samples[var14] = 0; + } + } + if (this.delayTime > 0 && this.delayDecay > 0) + { + for (var12 = var11 = (int) ((double) this.delayTime * var3); var12 < var1; ++var12) + { + int[] arrn = samples; + int n = var12; + + arrn[n] = arrn[n] + samples[var12 - var11] * this.delayDecay / 100; + } + } + if (this.filter.pairs[0] > 0 || this.filter.pairs[1] > 0) + { + this.filterEnvelope.reset(); + + var11 = this.filterEnvelope.step(var1 + 1); + var12 = this.filter.compute(0, (float) var11 / 65536.0f); + var13 = this.filter.compute(1, (float) var11 / 65536.0f); + + if (var1 >= var12 + var13) + { + int var17; + + var14 = 0; + var15 = var13; + + if (var13 > var1 - var12) + { + var15 = var1 - var12; + } + + while (var14 < var15) + { + var16 = (int) ((long) samples[var14 + var12] * (long) SoundEffectDefinition.fowardMultiplier >> 16); + + for (var17 = 0; var17 < var12; ++var17) + { + var16 += (int) ((long) samples[var14 + var12 - 1 - var17] * (long) SoundEffectDefinition.coefficients[0][var17] >> 16); + } + + for (var17 = 0; var17 < var14; ++var17) + { + var16 -= (int) ((long) samples[var14 - 1 - var17] * (long) SoundEffectDefinition.coefficients[1][var17] >> 16); + } + + InstrumentDefinition.samples[var14] = var16; + var11 = this.filterEnvelope.step(var1 + 1); + ++var14; + } + var15 = 128; + + do + { + int var18; + + if (var15 > var1 - var12) + { + var15 = var1 - var12; + } + + while (var14 < var15) + { + var17 = (int) ((long) samples[var14 + var12] * (long) SoundEffectDefinition.fowardMultiplier >> 16); + + for (var18 = 0; var18 < var12; ++var18) + { + var17 += (int) ((long) samples[var14 + var12 - 1 - var18] * (long) SoundEffectDefinition.coefficients[0][var18] >> 16); + } + + for (var18 = 0; var18 < var13; ++var18) + { + var17 -= (int) ((long) samples[var14 - 1 - var18] * (long) SoundEffectDefinition.coefficients[1][var18] >> 16); + } + + InstrumentDefinition.samples[var14] = var17; + var11 = this.filterEnvelope.step(var1 + 1); + ++var14; + } + if (var14 >= var1 - var12) + { + while (var14 < var1) + { + var17 = 0; + for (var18 = var14 + var12 - var1; var18 < var12; ++var18) + { + var17 += (int) ((long) samples[var14 + var12 - 1 - var18] + * (long) SoundEffectDefinition.coefficients[0][var18] >> 16); + } + for (var18 = 0; var18 < var13; ++var18) + { + var17 -= (int) ((long) samples[var14 - 1 - var18] + * (long) SoundEffectDefinition.coefficients[1][var18] >> 16); + } + InstrumentDefinition.samples[var14] = var17; + this.filterEnvelope.step(var1 + 1); + ++var14; + } + break; + } + var12 = this.filter.compute(0, (float) var11 / 65536.0f); + var13 = this.filter.compute(1, (float) var11 / 65536.0f); + var15 += 128; + } + while (true); + } + } + for (var11 = 0; var11 < var1; ++var11) + { + if (samples[var11] < -32768) + { + InstrumentDefinition.samples[var11] = -32768; + } + + if (samples[var11] <= 32767) + { + continue; + } + + InstrumentDefinition.samples[var11] = 32767; + } + + return samples; + } + + private static void method3854(int[] var1, int var2, int var3) + { + var3 = var3 + var2 - 7; + + while (var2 < var3) + { + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + var1[var2++] = 0; + } + + while (var2 < (var3 += 7)) + { + var1[var2++] = 0; + } + } + + public final int evaluateWave(int var1, int var2, int var3) + { + return var3 == 1 ? ((var1 & 32767) < 16384 ? var2 : -var2) : (var3 == 2 ? AUDIO_SINE[var1 & 32767] * var2 >> 14 : (var3 == 3 ? (var2 * (var1 & 32767) >> 14) - var2 : (var3 == 4 ? var2 * NOISE[var1 / 2607 & 32767] : 0))); + } +} + diff --git a/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffectDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffectDefinition.java index 0eda10254e..7f6d71dc17 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffectDefinition.java +++ b/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffectDefinition.java @@ -26,7 +26,102 @@ package net.runelite.cache.definitions.sound; public class SoundEffectDefinition { - public int field1006; - public SoundEffect1Definition[] field1008 = new SoundEffect1Definition[10]; - public int field1009; -} + public int[][][] phases = new int[2][2][4]; + public int[] pairs = new int[2]; + public int[] unity = new int[2]; + public int[][][] magnitudes = new int[2][2][4]; + + public static float[][] minCoefficients = new float[2][8]; + public static int[][] coefficients = new int[2][8]; + public static float fowardMinCoefficientMultiplier; + public static int fowardMultiplier; + + public int compute(int var1, float var2) + { + float var3; + int var4; + + if (var1 == 0) + { + var3 = (float) this.unity[0] + (float) (this.unity[1] - this.unity[0]) * var2; + + fowardMinCoefficientMultiplier = (float) Math.pow(0.1, (var3 *= 0.0030517578f) / 20.0f); + fowardMultiplier = (int) (fowardMinCoefficientMultiplier * 65536.0f); + } + + if (this.pairs[var1] == 0) + { + return 0; + } + + var3 = this.interpolateMagniture(var1, 0, var2); + + minCoefficients[var1][0] = -2.0f * var3 * (float) Math.cos(this.interpolatePhase(var1, 0, var2)); + minCoefficients[var1][1] = var3 * var3; + + for (var4 = 1; var4 < this.pairs[var1]; ++var4) + { + var3 = this.interpolateMagniture(var1, var4, var2); + + float var5 = -2.0f * var3 * (float) Math.cos(this.interpolatePhase(var1, var4, var2)); + float var6 = var3 * var3; + + minCoefficients[var1][var4 * 2 + 1] = minCoefficients[var1][var4 * 2 - 1] * var6; + minCoefficients[var1][var4 * 2] = minCoefficients[var1][var4 * 2 - 1] * var5 + minCoefficients[var1][var4 * 2 - 2] * var6; + + for (int var7 = var4 * 2 - 1; var7 >= 2; --var7) + { + float[] arrf = minCoefficients[var1]; + int n = var7; + + arrf[n] = arrf[n] + (minCoefficients[var1][var7 - 1] * var5 + minCoefficients[var1][var7 - 2] * var6); + } + + float[] arrf = minCoefficients[var1]; + arrf[1] = arrf[1] + (minCoefficients[var1][0] * var5 + var6); + + float[] arrf2 = minCoefficients[var1]; + arrf2[0] = arrf2[0] + var5; + } + + if (var1 == 0) + { + var4 = 0; + while (var4 < this.pairs[0] * 2) + { + float[] arrf = minCoefficients[0]; + int n = var4++; + + arrf[n] = arrf[n] * fowardMinCoefficientMultiplier; + } + } + + for (var4 = 0; var4 < this.pairs[var1] * 2; ++var4) + { + coefficients[var1][var4] = (int) (minCoefficients[var1][var4] * 65536.0f); + } + + return this.pairs[var1] * 2; + } + + public float interpolateMagniture(int var1, int var2, float var3) + { + float var4 = (float) this.magnitudes[var1][0][var2] + var3 * (float) (this.magnitudes[var1][1][var2] - this.magnitudes[var1][0][var2]); + + return 1.0f - (float) Math.pow(10.0, (-(var4 *= 0.0015258789f)) / 20.0f); + } + + public float interpolatePhase(int var1, int var2, float var3) + { + float var4 = (float) this.phases[var1][0][var2] + var3 * (float) (this.phases[var1][1][var2] - this.phases[var1][0][var2]); + + return normalise(var4 *= 1.2207031E-4f); + } + + public static float normalise(float var1) + { + float var2 = 32.703197f * (float) Math.pow(2.0, var1); + + return var2 * 3.1415927f / 11025.0f; + } +} \ No newline at end of file diff --git a/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffect2Definition.java b/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffectTrackDefinition.java similarity index 56% rename from cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffect2Definition.java rename to cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffectTrackDefinition.java index 358d462f50..6cbbbcc2cf 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffect2Definition.java +++ b/cache/src/main/java/net/runelite/cache/definitions/sound/SoundEffectTrackDefinition.java @@ -24,25 +24,61 @@ */ package net.runelite.cache.definitions.sound; -public class SoundEffect2Definition +public class SoundEffectTrackDefinition { - public int field1085; - public int[] field1086 = new int[2]; - public int field1087; - public int field1088; - public int field1089; - public int[] field1090 = new int[2]; - public int field1091; - public int field1092 = 2; - public int field1093; - public int field1094; - public int field1095; + public int start; + public InstrumentDefinition[] instruments = new InstrumentDefinition[10]; + public int end; - public SoundEffect2Definition() + public final byte[] mix() { - this.field1086[0] = 0; - this.field1086[1] = '\uffff'; - this.field1090[0] = 0; - this.field1090[1] = '\uffff'; + int var2; + int var1 = 0; + + for (var2 = 0; var2 < 10; ++var2) + { + if (this.instruments[var2] == null || this.instruments[var2].duration + this.instruments[var2].offset <= var1) + { + continue; + } + + var1 = this.instruments[var2].duration + this.instruments[var2].offset; + } + + if (var1 == 0) + { + return new byte[0]; + } + + var2 = var1 * 22050 / 1000; + + byte[] var3 = new byte[var2]; + + for (int i = 0; i < 10; ++i) + { + if (this.instruments[i] == null) + { + continue; + } + + int var5 = this.instruments[i].duration * 22050 / 1000; + int var6 = this.instruments[i].offset * 22050 / 1000; + + int[] var7 = this.instruments[i].synthesize(var5, this.instruments[i].duration); + + for (int j = 0; j < var5; ++j) + { + int var9 = (var7[j] >> 8) + var3[j + var6]; + + if ((var9 + 128 & -256) != 0) + { + var9 = var9 >> 31 ^ 127; + } + + var3[j + var6] = (byte) var9; + } + } + + return var3; } -} +} \ No newline at end of file diff --git a/cache/src/test/java/net/runelite/cache/SoundEffectsDumperTest.java b/cache/src/test/java/net/runelite/cache/SoundEffectsDumperTest.java index 5ac0c9e1c5..ec332656b2 100644 --- a/cache/src/test/java/net/runelite/cache/SoundEffectsDumperTest.java +++ b/cache/src/test/java/net/runelite/cache/SoundEffectsDumperTest.java @@ -27,11 +27,16 @@ package net.runelite.cache; import com.google.common.io.Files; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import java.io.File; + + import java.io.IOException; +import java.io.File; +import java.io.FileOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; import java.nio.charset.Charset; -import net.runelite.cache.definitions.loaders.sound.SoundEffectLoader; -import net.runelite.cache.definitions.sound.SoundEffectDefinition; +import net.runelite.cache.definitions.loaders.sound.SoundEffectTrackLoader; +import net.runelite.cache.definitions.sound.SoundEffectTrackDefinition; import net.runelite.cache.fs.Archive; import net.runelite.cache.fs.Index; import net.runelite.cache.fs.Storage; @@ -42,6 +47,11 @@ import org.junit.rules.TemporaryFolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + public class SoundEffectsDumperTest { private static final Logger logger = LoggerFactory.getLogger(SoundEffectsDumperTest.class); @@ -68,14 +78,68 @@ public class SoundEffectsDumperTest { byte[] contents = archive.decompress(storage.loadArchive(archive)); - SoundEffectLoader soundEffectLoader = new SoundEffectLoader(); - SoundEffectDefinition soundEffect = soundEffectLoader.load(contents); + SoundEffectTrackLoader setLoader = new SoundEffectTrackLoader(); + SoundEffectTrackDefinition soundEffect = setLoader.load(contents); - Files.asCharSink(new File(dumpDir, archive.getArchiveId() + ".json"), Charset.defaultCharset()).write(gson.toJson(soundEffect)); + Files.write(gson.toJson(soundEffect), new File(dumpDir, archive.getArchiveId() + ".json"), Charset.defaultCharset()); ++count; } } logger.info("Dumped {} sound effects to {}", count, dumpDir); } -} + + @Test + public void extractWavTest() throws IOException + { + File dumpDir = folder.newFolder(); + int count = 0; + + try (Store store = new Store(StoreLocation.LOCATION)) + { + store.load(); + + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.SOUNDEFFECTS); + + for (Archive archive : index.getArchives()) + { + byte[] contents = archive.decompress(storage.loadArchive(archive)); + + SoundEffectTrackLoader setLoader = new SoundEffectTrackLoader(); + SoundEffectTrackDefinition soundEffect = setLoader.load(contents); + try + { + Object audioStream; + byte[] data = soundEffect.mix(); + + AudioFormat audioFormat = new AudioFormat(22050.0f, 8, 1, true, false); + audioStream = new AudioInputStream(new ByteArrayInputStream(data), audioFormat, data.length); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + AudioSystem.write((AudioInputStream) audioStream, AudioFileFormat.Type.WAVE, bos); + data = bos.toByteArray(); + + FileOutputStream fos = new FileOutputStream(new File(dumpDir, archive.getArchiveId() + ".wav")); + + try + { + fos.write(data); + } + finally + { + fos.close(); + } + + ++count; + } + catch (Exception e) + { + continue; + } + } + } + + logger.info("Dumped {} sound effects to {}", count, dumpDir); + } +} \ No newline at end of file diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index bf9d9ef83d..8175174cea 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -284,13 +284,23 @@ asm-all 6.0_BETA - - org.codehaus.plexus - plexus-utils - 3.0.21 - compile - - + + org.codehaus.plexus + plexus-utils + 3.0.21 + compile + + + org.apache.httpcomponents + httpcore + 4.4.11 + + + org.apache.httpcomponents + httpmime + 4.5.9 + + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/PluginWatcher.java b/runelite-client/src/main/java/net/runelite/client/plugins/PluginWatcher.java index 870ccaaaf7..59a89d612d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/PluginWatcher.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/PluginWatcher.java @@ -41,6 +41,7 @@ import java.nio.file.WatchService; import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; + import lombok.extern.slf4j.Slf4j; import net.runelite.client.RuneLite; import net.runelite.client.config.Config; @@ -154,7 +155,6 @@ public class PluginWatcher extends Thread { continue; } - log.info("Loading plugin from {}", file); load(file); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPlugin.java index 0996eed283..7df1fbd6cb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPlugin.java @@ -25,11 +25,14 @@ package net.runelite.client.plugins.config; import java.awt.image.BufferedImage; +import java.lang.reflect.Method; import java.util.concurrent.ScheduledExecutorService; import javax.inject.Inject; import javax.inject.Singleton; import javax.swing.SwingUtilities; import net.runelite.api.MenuAction; +import net.runelite.client.RuneLite; +import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ChatColorConfig; import net.runelite.client.config.ConfigManager; import net.runelite.client.config.RuneLiteConfig; @@ -41,6 +44,7 @@ import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginManager; import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.ClientUI; import net.runelite.client.ui.NavigationButton; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayMenuEntry; @@ -97,9 +101,25 @@ public class ConfigPlugin extends Plugin } @Override - protected void shutDown() throws Exception + public void shutDown() throws Exception { clientToolbar.removeNavigation(navButton); + RuneLite.getInjector().getInstance(ClientThread.class).invokeLater(() -> + { + try + { + ConfigPanel.pluginList.clear(); + pluginManager.setPluginEnabled(this, true); + pluginManager.startPlugin(this); + Method expand = ClientUI.class.getDeclaredMethod("expand", NavigationButton.class); + expand.setAccessible(true); + expand.invoke(RuneLite.getInjector().getInstance(ClientUI.class), navButton); + } + catch (Exception e) + { + System.out.println(e.getMessage()); + } + }); } @Subscribe diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerConfig.java index 07e68ee198..bbb246f495 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerConfig.java @@ -166,6 +166,17 @@ public interface SlayerConfig extends Config return true; } + @ConfigItem( + position = 14, + keyName = "pointsCommand", + name = "Points Command", + description = "Configures whether the slayer points command is enabled
!points" + ) + default boolean pointsCommand() + { + return true; + } + // Stored data @ConfigItem( keyName = "taskName", diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java index 2c9e181905..eee2b5beeb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java @@ -139,6 +139,7 @@ public class SlayerPlugin extends Plugin private static final String TASK_COMMAND_STRING = "!task"; private static final Pattern TASK_STRING_VALIDATION = Pattern.compile("[^a-zA-Z0-9' -]"); private static final int TASK_STRING_MAX_LENGTH = 50; + private static final String POINTS_COMMAND_STRING = "!points"; // Superiors @VisibleForTesting @@ -280,6 +281,8 @@ public class SlayerPlugin extends Plugin private boolean taskCommand; private String taskName; private String taskLocation; + @Setter(AccessLevel.PACKAGE) + private boolean pointsCommand; private int amount; private int initialAmount; private int lastCertainAmount; @@ -316,6 +319,8 @@ public class SlayerPlugin extends Plugin clientToolbar.addNavigation(navButton); chatCommandManager.registerCommandAsync(TASK_COMMAND_STRING, this::taskLookup, this::taskSubmit); + + chatCommandManager.registerCommandAsync(POINTS_COMMAND_STRING, this::pointsLookup); //here } @Override @@ -329,6 +334,7 @@ public class SlayerPlugin extends Plugin clearTrackedNPCs(); chatCommandManager.unregisterCommand(TASK_COMMAND_STRING); + chatCommandManager.unregisterCommand(POINTS_COMMAND_STRING); clientToolbar.removeNavigation(navButton); } @@ -1121,6 +1127,44 @@ public class SlayerPlugin extends Plugin client.refreshChat(); } + void pointsLookup(ChatMessage chatMessage, String message) + { + if (!this.pointsCommand) + { + return; + } + + ChatMessageType type = chatMessage.getType(); + + final String player; + if (type.equals(ChatMessageType.PRIVATECHATOUT)) + { + player = client.getLocalPlayer().getName(); + } + else + { + player = Text.removeTags(chatMessage.getName()) + .replace('\u00A0', ' '); + } + + if (Integer.toString(getPoints()) == null) + { + return; + } + + String response = new ChatMessageBuilder() + .append(ChatColorType.NORMAL) + .append("Slayer Points: ") + .append(ChatColorType.HIGHLIGHT) + .append(Integer.toString(getPoints())) + .build(); + + final MessageNode messageNode = chatMessage.getMessageNode(); + messageNode.setRuneLiteFormatMessage(response); + chatMessageManager.update(messageNode); + client.refreshChat(); + } + /* package access method for changing the pause state of the time tracker for the current task */ void setPaused(boolean paused) { @@ -1208,6 +1252,7 @@ public class SlayerPlugin extends Plugin this.drawMinimapNames = config.drawMinimapNames(); this.weaknessPrompt = config.weaknessPrompt(); this.taskCommand = config.taskCommand(); + this.pointsCommand = config.pointsCommand(); this.taskName = config.taskName(); this.amount = config.amount(); this.initialAmount = config.initialAmount();