Merge branch 'loose-ends' into runelite
This commit is contained in:
@@ -2075,4 +2075,8 @@ public interface Client extends GameShell
|
||||
ScriptEvent createScriptEvent(Object[] args);
|
||||
|
||||
int getViewportColor();
|
||||
|
||||
NodeCache getStructCompositionCache();
|
||||
|
||||
void setMusicVolume(int i);
|
||||
}
|
||||
|
||||
57
runelite-api/src/main/java/net/runelite/api/ParamHolder.java
Normal file
57
runelite-api/src/main/java/net/runelite/api/ParamHolder.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.api;
|
||||
|
||||
/**
|
||||
* A composition that can hold `param` keys. This lets Jagex attach arbitrary constant
|
||||
* data to certain items, objects, npcs, or structs for use in cs2
|
||||
*
|
||||
* @see ParamID
|
||||
*/
|
||||
public interface ParamHolder
|
||||
{
|
||||
IterableHashTable<Node> getParams();
|
||||
void setParams(IterableHashTable<Node> params);
|
||||
|
||||
/**
|
||||
* Gets the value of a given {@link ParamID}, or its default if it is unset
|
||||
*/
|
||||
int getIntValue(int paramID);
|
||||
|
||||
/**
|
||||
* Sets the value of a given {@link ParamID}
|
||||
*/
|
||||
void setValue(int paramID, int value);
|
||||
|
||||
/**
|
||||
* Gets the value of a given {@link ParamID}, or its default if it is unset
|
||||
*/
|
||||
String getStringValue(int paramID);
|
||||
|
||||
/**
|
||||
* Sets the value of a given {@link ParamID}
|
||||
*/
|
||||
void setValue(int paramID, String value);
|
||||
}
|
||||
48
runelite-api/src/main/java/net/runelite/api/ParamID.java
Normal file
48
runelite-api/src/main/java/net/runelite/api/ParamID.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.api;
|
||||
|
||||
/**
|
||||
* @see ParamHolder
|
||||
*/
|
||||
public class ParamID
|
||||
{
|
||||
/**
|
||||
* @see SettingID
|
||||
*/
|
||||
public static final int SETTING_ID = 1077;
|
||||
// defaults to 5
|
||||
// 1 is continuous
|
||||
public static final int SETTING_SLIDER_STEPS = 1101;
|
||||
public static final int SETTING_CUSTOM_TRANSMIT = 1085;
|
||||
// defaults to true
|
||||
// track is foreground
|
||||
public static final int SETTING_FOREGROUND_CLICKZONE = 1105;
|
||||
public static final int SETTING_SLIDER_CUSTOM_ONOP = 1106;
|
||||
public static final int SETTING_SLIDER_CUSTOM_SETPOS = 1107;
|
||||
public static final int SETTING_SLIDER_IS_DRAGGABLE = 1108;
|
||||
public static final int SETTING_SLIDER_DEADZONE = 1109;
|
||||
public static final int SETTING_SLIDER_DEADTIME = 1110;
|
||||
}
|
||||
@@ -1596,4 +1596,8 @@ public final class SpriteID
|
||||
public static final int FRIENDS_CHAT_RANK_TRIPLE_CHEVRON_SERGEANT = 2831;
|
||||
public static final int FRIENDS_CHAT_RANK_DOUBLE_CHEVRON_CORPORAL = 2832;
|
||||
public static final int FRIENDS_CHAT_RANK_SINGLE_CHEVRON_RECRUIT = 2833;
|
||||
|
||||
public static final int SETTINGS_SLIDER_HANDLE_BLUE = 2858;
|
||||
public static final int SETTINGS_SLIDER_HANDLE_RED = 2859;
|
||||
public static final int SETTINGS_SLIDER_HANDLE_GREEN = 2860;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.api;
|
||||
|
||||
/**
|
||||
* A config type dedicated to holding params.
|
||||
*
|
||||
* Historically items were often used for this before structs were made
|
||||
* available, and there are many of these still around.
|
||||
*
|
||||
* @see ParamHolder
|
||||
*/
|
||||
public interface StructComposition extends ParamHolder
|
||||
{
|
||||
int getId();
|
||||
}
|
||||
37
runelite-api/src/main/java/net/runelite/api/StructID.java
Normal file
37
runelite-api/src/main/java/net/runelite/api/StructID.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.runelite.api;
|
||||
|
||||
/**
|
||||
* @see StructComposition
|
||||
* @see Client#getStructComposition(int)
|
||||
*/
|
||||
public class StructID
|
||||
{
|
||||
public static final int SETTINGS_MUSIC_VOLUME = 2753;
|
||||
public static final int SETTINGS_EFFECT_VOLUME = 2754;
|
||||
public static final int SETTINGS_AREA_VOLUME = 2755;
|
||||
}
|
||||
@@ -784,6 +784,13 @@ public enum Varbits
|
||||
LEAGUE_RELIC_5(10053),
|
||||
LEAGUE_RELIC_6(11696),
|
||||
|
||||
/**
|
||||
* Muted volume restore values
|
||||
*/
|
||||
MUTED_MUSIC_VOLUME(9666),
|
||||
MUTED_SOUND_EFFECT_VOLUME(9674),
|
||||
MUTED_AREA_EFFECT_VOLUME(9675),
|
||||
|
||||
/**
|
||||
* Whether the Special Attack orb is disabled due to being in a PvP area
|
||||
*
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Abex
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.api.events;
|
||||
|
||||
import lombok.Data;
|
||||
import net.runelite.api.StructComposition;
|
||||
|
||||
/**
|
||||
* An event called after a new {@link StructComposition} is created and
|
||||
* its data is initialized.
|
||||
*/
|
||||
@Data
|
||||
public class PostStructComposition
|
||||
{
|
||||
/**
|
||||
* The newly created struct.
|
||||
*/
|
||||
private StructComposition structComposition;
|
||||
}
|
||||
@@ -1026,4 +1026,36 @@ public interface Widget
|
||||
System.out.println("ERROR: IMPLEMENT"); //Would throw but that breaks widget inspector
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a script to be ran when a drag operation is finished on this widget
|
||||
*
|
||||
* @param args A ScriptID, then the args for the script
|
||||
*/
|
||||
void setOnDragCompleteListener(Object ...args);
|
||||
|
||||
/**
|
||||
* Sets a script to be ran when this widget moves due to a drag
|
||||
*
|
||||
* @param args A ScriptID, then the args for the script
|
||||
*/
|
||||
void setOnDragListener(Object ...args);
|
||||
|
||||
/**
|
||||
* Container this can be dragged in
|
||||
*/
|
||||
Widget getDragParent();
|
||||
|
||||
/**
|
||||
* Container this can be dragged in
|
||||
*/
|
||||
void setDragParent(Widget dragParent);
|
||||
|
||||
/**
|
||||
* Sets a script to be ran when a varplayer changes
|
||||
*
|
||||
* @param args A ScriptID, then the args for the script
|
||||
*/
|
||||
void setOnVarTransmitListener(Object ...args);
|
||||
}
|
||||
}
|
||||
@@ -888,6 +888,12 @@ public enum WidgetInfo
|
||||
SEED_VAULT_ITEM_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_CONTAINER),
|
||||
SEED_VAULT_ITEM_TEXT(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_TEXT),
|
||||
SEED_VAULT_INVENTORY_ITEMS_CONTAINER(WidgetID.SEED_VAULT_INVENTORY_GROUP_ID, WidgetID.SeedVault.INVENTORY_ITEM_CONTAINER),
|
||||
|
||||
SETTINGS_SIDE_CAMERA_ZOOM_SLIDER_TRACK(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.CAMERA_ZOOM_SLIDER_TRACK),
|
||||
SETTINGS_SIDE_MUSIC_SLIDER(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.MUSIC_SLIDER),
|
||||
SETTINGS_SIDE_SOUND_EFFECT_SLIDER(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.SOUND_EFFECT_SLIDER),
|
||||
SETTINGS_SIDE_AREA_SOUND_SLIDER(WidgetID.SETTINGS_SIDE_GROUP_ID, WidgetID.SettingsSide.AREA_SOUND_SLIDER),
|
||||
|
||||
JEWELLERY_BOX_DUEL_RING(WidgetID.JEWELLERY_BOX_GROUP_ID, WidgetID.JewelBox.DUEL_RING),
|
||||
JEWELLERY_BOX_GAME_NECK(WidgetID.JEWELLERY_BOX_GROUP_ID, WidgetID.JewelBox.GAME_NECK),
|
||||
JEWELLERY_BOX_COMB_BRAC(WidgetID.JEWELLERY_BOX_GROUP_ID, WidgetID.JewelBox.COMB_BRAC),
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* 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.client.plugins.music;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("music")
|
||||
public interface MusicConfig extends Config
|
||||
{
|
||||
String GRANULAR_SLIDERS = "granularSliders";
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "muteOwnAreaSounds",
|
||||
name = "Mute player area sounds",
|
||||
description = "Mute area sounds caused by yourself",
|
||||
position = 0
|
||||
)
|
||||
default boolean muteOwnAreaSounds()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "muteOtherAreaSounds",
|
||||
name = "Mute other players' area sounds",
|
||||
description = "Mute area sounds caused by other players",
|
||||
position = 1
|
||||
)
|
||||
default boolean muteOtherAreaSounds()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "muteOtherAreaNPCSounds",
|
||||
name = "Mute NPCs' area sounds",
|
||||
description = "Mute area sounds caused by NPCs",
|
||||
position = 2
|
||||
)
|
||||
default boolean muteNpcAreaSounds()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "muteOtherAreaEnvironmentSounds",
|
||||
name = "Mute environment area sounds",
|
||||
description = "Mute area sounds caused by neither NPCs nor players",
|
||||
position = 3
|
||||
)
|
||||
default boolean muteEnvironmentAreaSounds()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "mutePrayerSounds",
|
||||
name = "Mute prayer sounds",
|
||||
description = "Mute prayer activation and deactivation sounds",
|
||||
position = 4
|
||||
)
|
||||
default boolean mutePrayerSounds()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = GRANULAR_SLIDERS,
|
||||
name = "Granular volume sliders",
|
||||
description = "Make the volume sliders allow better control of volume",
|
||||
position = 5
|
||||
)
|
||||
default boolean granularSliders()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "musicVolume",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default int getMusicVolume()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "musicVolume",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
void setMusicVolume(int vol);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "soundEffectVolume",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default int getSoundEffectVolume()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "soundEffectVolume",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
void setSoundEffectVolume(int val);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "areaSoundEffectVolume",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default int getAreaSoundEffectVolume()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "areaSoundEffectVolume",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
void setAreaSoundEffectVolume(int vol);
|
||||
}
|
||||
@@ -0,0 +1,927 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Anthony Chen <https://github.com/achencoms>
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2020, Sean Dewar <https://github.com/seandewar>
|
||||
* 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.client.plugins.music;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.google.inject.Provides;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.ParamID;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Preferences;
|
||||
import net.runelite.api.ScriptEvent;
|
||||
import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.SettingID;
|
||||
import net.runelite.api.SoundEffectID;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.StructComposition;
|
||||
import net.runelite.api.StructID;
|
||||
import net.runelite.api.VarClientInt;
|
||||
import net.runelite.api.VarPlayer;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.AreaSoundEffectPlayed;
|
||||
import net.runelite.api.events.BeforeRender;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.PostStructComposition;
|
||||
import net.runelite.api.events.ScriptPreFired;
|
||||
import net.runelite.api.events.SoundEffectPlayed;
|
||||
import net.runelite.api.events.VarClientIntChanged;
|
||||
import net.runelite.api.events.VolumeChanged;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.widgets.JavaScriptCallback;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetPositionMode;
|
||||
import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.game.chatbox.ChatboxTextInput;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.tooltip.Tooltip;
|
||||
import net.runelite.client.ui.overlay.tooltip.TooltipManager;
|
||||
|
||||
@Slf4j
|
||||
@PluginDescriptor(
|
||||
name = "Music",
|
||||
description = "Adds search and filter for the music list, and additional volume control",
|
||||
tags = {"sound", "volume"}
|
||||
)
|
||||
public class MusicPlugin extends Plugin
|
||||
{
|
||||
private static final int SLIDER_HANDLE_SIZE = 16;
|
||||
|
||||
private static final Set<Integer> SOURCELESS_PLAYER_SOUNDS = ImmutableSet.of(
|
||||
SoundEffectID.TELEPORT_VWOOP
|
||||
);
|
||||
|
||||
private static final Set<Integer> PRAYER_SOUNDS = ImmutableSet.of(
|
||||
SoundEffectID.PRAYER_ACTIVATE_THICK_SKIN,
|
||||
SoundEffectID.PRAYER_ACTIVATE_BURST_OF_STRENGTH,
|
||||
SoundEffectID.PRAYER_ACTIVATE_CLARITY_OF_THOUGHT,
|
||||
SoundEffectID.PRAYER_ACTIVATE_SHARP_EYE_RIGOUR,
|
||||
SoundEffectID.PRAYER_ACTIVATE_MYSTIC_WILL_AUGURY,
|
||||
SoundEffectID.PRAYER_ACTIVATE_ROCK_SKIN,
|
||||
SoundEffectID.PRAYER_ACTIVATE_SUPERHUMAN_STRENGTH,
|
||||
SoundEffectID.PRAYER_ACTIVATE_IMPROVED_REFLEXES,
|
||||
SoundEffectID.PRAYER_ACTIVATE_RAPID_RESTORE_PRESERVE,
|
||||
SoundEffectID.PRAYER_ACTIVATE_RAPID_HEAL,
|
||||
SoundEffectID.PRAYER_ACTIVATE_PROTECT_ITEM,
|
||||
SoundEffectID.PRAYER_ACTIVATE_HAWK_EYE,
|
||||
SoundEffectID.PRAYER_ACTIVATE_MYSTIC_LORE,
|
||||
SoundEffectID.PRAYER_ACTIVATE_STEEL_SKIN,
|
||||
SoundEffectID.PRAYER_ACTIVATE_ULTIMATE_STRENGTH,
|
||||
SoundEffectID.PRAYER_ACTIVATE_INCREDIBLE_REFLEXES,
|
||||
SoundEffectID.PRAYER_ACTIVATE_PROTECT_FROM_MAGIC,
|
||||
SoundEffectID.PRAYER_ACTIVATE_PROTECT_FROM_MISSILES,
|
||||
SoundEffectID.PRAYER_ACTIVATE_PROTECT_FROM_MELEE,
|
||||
SoundEffectID.PRAYER_ACTIVATE_EAGLE_EYE,
|
||||
SoundEffectID.PRAYER_ACTIVATE_MYSTIC_MIGHT,
|
||||
SoundEffectID.PRAYER_ACTIVATE_RETRIBUTION,
|
||||
SoundEffectID.PRAYER_ACTIVATE_REDEMPTION,
|
||||
SoundEffectID.PRAYER_ACTIVATE_SMITE,
|
||||
SoundEffectID.PRAYER_ACTIVATE_CHIVALRY,
|
||||
SoundEffectID.PRAYER_ACTIVATE_PIETY,
|
||||
SoundEffectID.PRAYER_DEACTIVE_VWOOP
|
||||
);
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private MusicConfig musicConfig;
|
||||
|
||||
@Inject
|
||||
private ChatboxPanelManager chatboxPanelManager;
|
||||
|
||||
@Inject
|
||||
private TooltipManager tooltipManager;
|
||||
|
||||
private Channel musicChannel;
|
||||
private Channel effectChannel;
|
||||
private Channel areaChannel;
|
||||
private Channel[] channels;
|
||||
|
||||
private ChatboxTextInput searchInput;
|
||||
|
||||
private Widget musicSearchButton;
|
||||
private Widget musicFilterButton;
|
||||
|
||||
private Collection<Widget> tracks;
|
||||
|
||||
private MusicState currentMusicFilter = MusicState.ALL;
|
||||
|
||||
private Tooltip sliderTooltip;
|
||||
private boolean shuttingDown = false;
|
||||
|
||||
@Override
|
||||
protected void startUp()
|
||||
{
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
this.shuttingDown = false;
|
||||
|
||||
Preferences preferences = client.getPreferences();
|
||||
musicChannel = new Channel("Music",
|
||||
VarPlayer.MUSIC_VOLUME, Varbits.MUTED_MUSIC_VOLUME,
|
||||
musicConfig::getMusicVolume, musicConfig::setMusicVolume,
|
||||
client::setMusicVolume, 255,
|
||||
WidgetInfo.SETTINGS_SIDE_MUSIC_SLIDER);
|
||||
effectChannel = new Channel("Sound Effects",
|
||||
VarPlayer.SOUND_EFFECT_VOLUME, Varbits.MUTED_SOUND_EFFECT_VOLUME,
|
||||
musicConfig::getSoundEffectVolume, musicConfig::setSoundEffectVolume,
|
||||
preferences::setSoundEffectVolume, 127,
|
||||
WidgetInfo.SETTINGS_SIDE_SOUND_EFFECT_SLIDER);
|
||||
areaChannel = new Channel("Area Sounds",
|
||||
VarPlayer.AREA_EFFECT_VOLUME, Varbits.MUTED_AREA_EFFECT_VOLUME,
|
||||
musicConfig::getAreaSoundEffectVolume, musicConfig::setAreaSoundEffectVolume,
|
||||
preferences::setAreaSoundEffectVolume, 127,
|
||||
WidgetInfo.SETTINGS_SIDE_AREA_SOUND_SLIDER);
|
||||
channels = new Channel[]{musicChannel, effectChannel, areaChannel};
|
||||
|
||||
addMusicButtons();
|
||||
updateMusicOptions();
|
||||
resetSettingsWindow();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
Widget header = client.getWidget(WidgetInfo.MUSIC_WINDOW);
|
||||
if (header != null)
|
||||
{
|
||||
header.deleteAllChildren();
|
||||
}
|
||||
|
||||
tracks = null;
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
shuttingDown = true;
|
||||
teardownMusicOptions();
|
||||
});
|
||||
}
|
||||
|
||||
@Provides
|
||||
MusicConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(MusicConfig.class);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||
{
|
||||
if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
// Reset music filter on logout
|
||||
currentMusicFilter = MusicState.ALL;
|
||||
tracks = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWidgetLoaded(WidgetLoaded widgetLoaded)
|
||||
{
|
||||
if (widgetLoaded.getGroupId() == WidgetID.MUSIC_GROUP_ID)
|
||||
{
|
||||
tracks = null;
|
||||
// Reset filter state as the widget has been reloaded.
|
||||
// It is too early here to call updateFilter()
|
||||
currentMusicFilter = MusicState.ALL;
|
||||
addMusicButtons();
|
||||
}
|
||||
|
||||
if ((widgetLoaded.getGroupId() == WidgetID.SETTINGS_GROUP_ID || widgetLoaded.getGroupId() == WidgetID.SETTINGS_SIDE_GROUP_ID)
|
||||
&& musicConfig.granularSliders())
|
||||
{
|
||||
updateMusicOptions();
|
||||
}
|
||||
}
|
||||
|
||||
private void addMusicButtons()
|
||||
{
|
||||
Widget header = client.getWidget(WidgetInfo.MUSIC_WINDOW);
|
||||
|
||||
if (header == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
header.deleteAllChildren();
|
||||
|
||||
//Creation of the search and toggle status buttons
|
||||
musicSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
musicSearchButton.setSpriteId(SpriteID.GE_SEARCH);
|
||||
musicSearchButton.setOriginalWidth(18);
|
||||
musicSearchButton.setOriginalHeight(17);
|
||||
musicSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
musicSearchButton.setOriginalX(5);
|
||||
musicSearchButton.setOriginalY(32);
|
||||
musicSearchButton.setHasListener(true);
|
||||
musicSearchButton.setAction(1, "Open");
|
||||
musicSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||
musicSearchButton.setName("Search");
|
||||
musicSearchButton.revalidate();
|
||||
|
||||
musicFilterButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
musicFilterButton.setSpriteId(SpriteID.MINIMAP_ORB_PRAYER);
|
||||
musicFilterButton.setOriginalWidth(15);
|
||||
musicFilterButton.setOriginalHeight(15);
|
||||
musicFilterButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
musicFilterButton.setOriginalX(25);
|
||||
musicFilterButton.setOriginalY(34);
|
||||
musicFilterButton.setHasListener(true);
|
||||
musicFilterButton.setAction(1, "Toggle");
|
||||
musicFilterButton.setOnOpListener((JavaScriptCallback) e -> toggleStatus());
|
||||
musicFilterButton.setName("All");
|
||||
musicFilterButton.revalidate();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged)
|
||||
{
|
||||
if (isChatboxOpen() && !isOnMusicTab())
|
||||
{
|
||||
chatboxPanelManager.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVolumeChanged(VolumeChanged volumeChanged)
|
||||
{
|
||||
if (musicConfig.granularSliders())
|
||||
{
|
||||
updateMusicOptions();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged configChanged)
|
||||
{
|
||||
if ("music".equals(configChanged.getGroup()))
|
||||
{
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
if (MusicConfig.GRANULAR_SLIDERS.equals(configChanged.getKey()))
|
||||
{
|
||||
if (musicConfig.granularSliders())
|
||||
{
|
||||
updateMusicOptions();
|
||||
resetSettingsWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
teardownMusicOptions();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
updateMusicOptions();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOnMusicTab()
|
||||
{
|
||||
return client.getVar(VarClientInt.INVENTORY_TAB) == 13;
|
||||
}
|
||||
|
||||
private boolean isChatboxOpen()
|
||||
{
|
||||
return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput;
|
||||
}
|
||||
|
||||
private String getChatboxInput()
|
||||
{
|
||||
return isChatboxOpen() ? searchInput.getValue() : "";
|
||||
}
|
||||
|
||||
private void toggleStatus()
|
||||
{
|
||||
MusicState[] states = MusicState.values();
|
||||
currentMusicFilter = states[(currentMusicFilter.ordinal() + 1) % states.length];
|
||||
musicFilterButton.setSpriteId(currentMusicFilter.getSpriteID());
|
||||
musicFilterButton.setName(currentMusicFilter.getName());
|
||||
updateFilter(getChatboxInput());
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
}
|
||||
|
||||
private void openSearch()
|
||||
{
|
||||
updateFilter("");
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
musicSearchButton.setAction(1, "Close");
|
||||
musicSearchButton.setOnOpListener((JavaScriptCallback) e -> closeSearch());
|
||||
searchInput = chatboxPanelManager.openTextInput("Search music list")
|
||||
.onChanged(s -> clientThread.invokeLater(() -> updateFilter(s.trim())))
|
||||
.onDone(s -> false)
|
||||
.onClose(() ->
|
||||
{
|
||||
clientThread.invokeLater(() -> updateFilter(""));
|
||||
musicSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||
musicSearchButton.setAction(1, "Open");
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
private void closeSearch()
|
||||
{
|
||||
updateFilter("");
|
||||
chatboxPanelManager.close();
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
}
|
||||
|
||||
private void updateFilter(String input)
|
||||
{
|
||||
final Widget container = client.getWidget(WidgetInfo.MUSIC_WINDOW);
|
||||
final Widget musicList = client.getWidget(WidgetInfo.MUSIC_TRACK_LIST);
|
||||
|
||||
if (container == null || musicList == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String filter = input.toLowerCase();
|
||||
updateList(musicList, filter);
|
||||
}
|
||||
|
||||
private void updateList(Widget musicList, String filter)
|
||||
{
|
||||
if (tracks == null)
|
||||
{
|
||||
tracks = Arrays.stream(musicList.getDynamicChildren())
|
||||
.sorted(Comparator.comparing(Widget::getRelativeY))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
tracks.forEach(w -> w.setHidden(true));
|
||||
|
||||
Collection<Widget> relevantTracks = tracks.stream()
|
||||
.filter(w -> w.getText().toLowerCase().contains(filter))
|
||||
.filter(w -> currentMusicFilter == MusicState.ALL || w.getTextColor() == currentMusicFilter.getColor())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Original music track list has a little offset
|
||||
int y = 3;
|
||||
|
||||
for (Widget track : relevantTracks)
|
||||
{
|
||||
track.setHidden(false);
|
||||
track.setOriginalY(y);
|
||||
track.revalidate();
|
||||
|
||||
y += track.getHeight();
|
||||
}
|
||||
|
||||
y += 3;
|
||||
|
||||
int newHeight = 0;
|
||||
|
||||
if (musicList.getScrollHeight() > 0)
|
||||
{
|
||||
newHeight = (musicList.getScrollY() * y) / musicList.getScrollHeight();
|
||||
}
|
||||
|
||||
musicList.setScrollHeight(y);
|
||||
musicList.revalidateScroll();
|
||||
|
||||
client.runScript(
|
||||
ScriptID.UPDATE_SCROLLBAR,
|
||||
WidgetInfo.MUSIC_TRACK_SCROLLBAR.getId(),
|
||||
WidgetInfo.MUSIC_TRACK_LIST.getId(),
|
||||
newHeight
|
||||
);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private enum MusicState
|
||||
{
|
||||
NOT_FOUND(0xff0000, "Locked", SpriteID.MINIMAP_ORB_HITPOINTS),
|
||||
FOUND(0xdc10d, "Unlocked", SpriteID.MINIMAP_ORB_HITPOINTS_POISON),
|
||||
ALL(0, "All", SpriteID.MINIMAP_ORB_PRAYER);
|
||||
|
||||
private final int color;
|
||||
private final String name;
|
||||
private final int spriteID;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private class Slider
|
||||
{
|
||||
@Getter
|
||||
protected final Channel channel;
|
||||
|
||||
protected Widget track;
|
||||
protected Widget handle;
|
||||
|
||||
public void update()
|
||||
{
|
||||
handle.setOnDragListener((JavaScriptCallback) this::drag);
|
||||
handle.setOnDragCompleteListener((JavaScriptCallback) this::drag);
|
||||
handle.setHasListener(true);
|
||||
|
||||
track.setOnMouseRepeatListener((JavaScriptCallback) ev ->
|
||||
{
|
||||
int value = channel.getValue();
|
||||
int percent = (int) Math.round((value * 100.0 / channel.getMax()));
|
||||
|
||||
sliderTooltip = new Tooltip(channel.getName() + ": " + percent + "%");
|
||||
});
|
||||
track.setOnClickListener((JavaScriptCallback) this::click);
|
||||
track.setHasListener(true);
|
||||
}
|
||||
|
||||
public void shutDown()
|
||||
{
|
||||
if (handle != null)
|
||||
{
|
||||
handle.setDragParent(null);
|
||||
handle.setOnDragListener((Object[]) null);
|
||||
handle.setOnDragCompleteListener((Object[]) null);
|
||||
}
|
||||
if (track != null)
|
||||
{
|
||||
track.setOnMouseRepeatListener((Object[]) null);
|
||||
track.setOnClickListener((Object[]) null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void drag(ScriptEvent ev)
|
||||
{
|
||||
moveHandle(ev.getMouseX());
|
||||
}
|
||||
|
||||
protected void click(ScriptEvent ev)
|
||||
{
|
||||
moveHandle(ev.getMouseX() - (SLIDER_HANDLE_SIZE / 2));
|
||||
}
|
||||
|
||||
protected void moveHandle(int x)
|
||||
{
|
||||
int level = (x * channel.max) / getWidth();
|
||||
level = Ints.constrainToRange(level, 0, channel.max);
|
||||
channel.setLevel(level);
|
||||
}
|
||||
|
||||
protected int getWidth()
|
||||
{
|
||||
return track.getWidth() - SLIDER_HANDLE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsSideSlider extends Slider
|
||||
{
|
||||
private final WidgetInfo root;
|
||||
private Widget icon;
|
||||
|
||||
SettingsSideSlider(Channel channel, WidgetInfo root)
|
||||
{
|
||||
super(channel);
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update()
|
||||
{
|
||||
Widget root = client.getWidget(this.root);
|
||||
if (root == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Object[] onLoad = root.getOnLoadListener();
|
||||
if (onLoad == null || onLoad.length != 5)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.icon = client.getWidget((Integer) onLoad[1]);
|
||||
this.track = client.getWidget((Integer) onLoad[2]);
|
||||
this.handle = client.getWidget((Integer) onLoad[3]);
|
||||
if (this.track == null || this.handle == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (Widget w : track.getChildren())
|
||||
{
|
||||
if (w != null)
|
||||
{
|
||||
w.setAction(0, null);
|
||||
}
|
||||
}
|
||||
|
||||
handle.setOnVarTransmitListener((Object[]) null);
|
||||
handle.setDragParent(track);
|
||||
handle.setSpriteId(SpriteID.SETTINGS_SLIDER_HANDLE_GREEN);
|
||||
super.update();
|
||||
|
||||
int val = channel.getValue();
|
||||
handle.setOriginalX((val * getWidth()) / channel.getMax());
|
||||
handle.revalidate();
|
||||
|
||||
// emulate [proc,settings_update_icon]
|
||||
boolean unmuted = val != 0;
|
||||
icon.getChild(1).setHidden(unmuted);
|
||||
icon.setAction(0, unmuted ? "Mute" : "Unmute");
|
||||
// Set name + no tooltip; we have our own for ops
|
||||
icon.setName(channel.getName());
|
||||
icon.setOnMouseRepeatListener((Object[]) null);
|
||||
icon.setOnOpListener((JavaScriptCallback) ev -> channel.toggleMute());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutDown()
|
||||
{
|
||||
super.shutDown();
|
||||
handle.setSpriteId(SpriteID.SETTINGS_SLIDER_HANDLE_BLUE);
|
||||
|
||||
this.icon.setOnOpListener((Object[]) null);
|
||||
|
||||
Widget root = client.getWidget(this.root);
|
||||
if (root != null)
|
||||
{
|
||||
client.createScriptEvent(root.getOnLoadListener())
|
||||
.setSource(root)
|
||||
.run();
|
||||
}
|
||||
|
||||
this.handle = this.track = this.icon = null;
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsSlider extends Slider
|
||||
{
|
||||
private final int offsetX;
|
||||
private final int offsetY;
|
||||
private final int width;
|
||||
private final Widget realTrack;
|
||||
|
||||
SettingsSlider(Channel channel, Widget handle, Widget track, int width, int offsetY, int offsetX, Widget realTrack)
|
||||
{
|
||||
super(channel);
|
||||
this.handle = handle;
|
||||
this.track = track;
|
||||
this.width = width;
|
||||
this.offsetX = offsetX;
|
||||
this.offsetY = offsetY;
|
||||
this.realTrack = realTrack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update()
|
||||
{
|
||||
super.update();
|
||||
|
||||
int val = channel.getValue();
|
||||
handle.setOriginalX(offsetX + (val * getWidth()) / channel.getMax());
|
||||
handle.setOriginalY(offsetY);
|
||||
handle.revalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getWidth()
|
||||
{
|
||||
return width - SLIDER_HANDLE_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void click(ScriptEvent ev)
|
||||
{
|
||||
super.click(ev);
|
||||
realTrack.setOriginalX(offsetX);
|
||||
realTrack.setOriginalY(offsetY);
|
||||
realTrack.setOriginalWidth(this.width);
|
||||
realTrack.setOriginalHeight(SLIDER_HANDLE_SIZE);
|
||||
realTrack.revalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("PMD.UselessOverridingMethod")
|
||||
public void shutDown()
|
||||
{
|
||||
// calling settings_init will do teardown for us
|
||||
super.shutDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onPostStructComposition(PostStructComposition ev)
|
||||
{
|
||||
if (shuttingDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
StructComposition sc = ev.getStructComposition();
|
||||
switch (sc.getId())
|
||||
{
|
||||
case StructID.SETTINGS_MUSIC_VOLUME:
|
||||
case StructID.SETTINGS_EFFECT_VOLUME:
|
||||
case StructID.SETTINGS_AREA_VOLUME:
|
||||
if (!musicConfig.granularSliders())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sc.setValue(ParamID.SETTING_SLIDER_STEPS, 1);
|
||||
sc.setValue(ParamID.SETTING_CUSTOM_TRANSMIT, 0);
|
||||
sc.setValue(ParamID.SETTING_FOREGROUND_CLICKZONE, 0);
|
||||
sc.setValue(ParamID.SETTING_SLIDER_CUSTOM_ONOP, 1);
|
||||
sc.setValue(ParamID.SETTING_SLIDER_CUSTOM_SETPOS, 1);
|
||||
sc.setValue(ParamID.SETTING_SLIDER_IS_DRAGGABLE, 1);
|
||||
sc.setValue(ParamID.SETTING_SLIDER_DEADZONE, 0);
|
||||
sc.setValue(ParamID.SETTING_SLIDER_DEADZONE, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onScriptPreFired(ScriptPreFired ev)
|
||||
{
|
||||
if (shuttingDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev.getScriptId() == ScriptID.SETTINGS_SLIDER_CHOOSE_ONOP)
|
||||
{
|
||||
if (!musicConfig.granularSliders())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int arg = client.getIntStackSize() - 7;
|
||||
int[] is = client.getIntStack();
|
||||
Channel channel;
|
||||
switch (is[arg])
|
||||
{
|
||||
case SettingID.MUSIC_VOLUME:
|
||||
channel = musicChannel;
|
||||
break;
|
||||
case SettingID.EFFECT_VOLUME:
|
||||
channel = effectChannel;
|
||||
break;
|
||||
case SettingID.AREA_VOLUME:
|
||||
channel = areaChannel;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
Widget track = client.getScriptActiveWidget();
|
||||
Widget handle = client.getWidget(is[arg + 1])
|
||||
.getChild(is[arg + 2]);
|
||||
Widget realTrack = client.getWidget(is[arg + 6]);
|
||||
SettingsSlider s = new SettingsSlider(channel, handle, track, is[arg + 3], is[arg + 4], is[arg + 5], realTrack);
|
||||
s.update();
|
||||
s.getChannel().setWindowSlider(s);
|
||||
}
|
||||
}
|
||||
|
||||
private class Channel
|
||||
{
|
||||
@Getter
|
||||
private final String name;
|
||||
private final VarPlayer var;
|
||||
private final Varbits mutedVar;
|
||||
private final IntSupplier getter;
|
||||
private final Consumer<Integer> setter;
|
||||
private final IntConsumer volumeChanger;
|
||||
|
||||
@Getter
|
||||
private final int max;
|
||||
|
||||
private final Slider sideSlider;
|
||||
|
||||
@Setter
|
||||
private Slider windowSlider;
|
||||
|
||||
Channel(String name,
|
||||
VarPlayer var, Varbits mutedVar,
|
||||
IntSupplier getter, Consumer<Integer> setter,
|
||||
IntConsumer volumeChanger, int max,
|
||||
WidgetInfo sideRoot)
|
||||
{
|
||||
this.name = name;
|
||||
this.var = var;
|
||||
this.mutedVar = mutedVar;
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
this.volumeChanger = volumeChanger;
|
||||
this.max = max;
|
||||
this.sideSlider = new SettingsSideSlider(this, sideRoot);
|
||||
}
|
||||
|
||||
private int getValueRaw()
|
||||
{
|
||||
int value = getter.getAsInt();
|
||||
if (value == 0)
|
||||
{
|
||||
// Use the vanilla value
|
||||
|
||||
// the varps are known by the engine and it requires they are stored so
|
||||
// 0 = max and 4 = muted
|
||||
int raw = 4 - client.getVar(var);
|
||||
if (raw == 0)
|
||||
{
|
||||
raw = -(4 - client.getVar(mutedVar));
|
||||
}
|
||||
value = ((raw * max) / 4);
|
||||
|
||||
// readd our 1 offset for unknown's place
|
||||
value += value < 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private int getValue()
|
||||
{
|
||||
int value = getValueRaw();
|
||||
|
||||
// muted with saved restore point
|
||||
if (value < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 0 is used for unknown, so config values are 1 away from zero
|
||||
return value - 1;
|
||||
}
|
||||
|
||||
public void toggleMute()
|
||||
{
|
||||
int val = -getValueRaw();
|
||||
if (val == -1)
|
||||
{
|
||||
// muted without a reset value
|
||||
val = max / 2;
|
||||
}
|
||||
setter.accept(val);
|
||||
}
|
||||
|
||||
public void setLevel(int level)
|
||||
{
|
||||
setter.accept(level + 1);
|
||||
update();
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
volumeChanger.accept(getValue());
|
||||
sideSlider.update();
|
||||
if (windowSlider != null)
|
||||
{
|
||||
windowSlider.update();
|
||||
}
|
||||
}
|
||||
|
||||
public void shutDown()
|
||||
{
|
||||
sideSlider.shutDown();
|
||||
if (windowSlider != null)
|
||||
{
|
||||
windowSlider.shutDown();
|
||||
}
|
||||
|
||||
int raw = 4 - client.getVar(var);
|
||||
int value = ((raw * max) / 4);
|
||||
volumeChanger.accept(value);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMusicOptions()
|
||||
{
|
||||
for (Channel channel : channels)
|
||||
{
|
||||
channel.update();
|
||||
}
|
||||
}
|
||||
|
||||
private void teardownMusicOptions()
|
||||
{
|
||||
// the side panel uses this too, so it has to run before they get shut down
|
||||
client.getStructCompositionCache().reset();
|
||||
|
||||
for (Channel channel : channels)
|
||||
{
|
||||
channel.shutDown();
|
||||
}
|
||||
|
||||
resetSettingsWindow();
|
||||
}
|
||||
|
||||
private void resetSettingsWindow()
|
||||
{
|
||||
client.getStructCompositionCache().reset();
|
||||
|
||||
Widget init = client.getWidget(WidgetInfo.SETTINGS_INIT);
|
||||
if (init != null)
|
||||
{
|
||||
// [clientscript, settings_init]
|
||||
client.createScriptEvent(init.getOnLoadListener())
|
||||
.setSource(init)
|
||||
.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onBeforeRender(BeforeRender ev)
|
||||
{
|
||||
if (sliderTooltip != null)
|
||||
{
|
||||
tooltipManager.add(sliderTooltip);
|
||||
sliderTooltip = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onAreaSoundEffectPlayed(AreaSoundEffectPlayed areaSoundEffectPlayed)
|
||||
{
|
||||
Actor source = areaSoundEffectPlayed.getSource();
|
||||
int soundId = areaSoundEffectPlayed.getSoundId();
|
||||
if (source == client.getLocalPlayer()
|
||||
&& musicConfig.muteOwnAreaSounds())
|
||||
{
|
||||
areaSoundEffectPlayed.consume();
|
||||
}
|
||||
else if (source != client.getLocalPlayer()
|
||||
&& (source instanceof Player || (source == null && SOURCELESS_PLAYER_SOUNDS.contains(soundId)))
|
||||
&& musicConfig.muteOtherAreaSounds())
|
||||
{
|
||||
areaSoundEffectPlayed.consume();
|
||||
}
|
||||
else if (source instanceof NPC
|
||||
&& musicConfig.muteNpcAreaSounds())
|
||||
{
|
||||
areaSoundEffectPlayed.consume();
|
||||
}
|
||||
else if (source == null
|
||||
&& !SOURCELESS_PLAYER_SOUNDS.contains(soundId)
|
||||
&& musicConfig.muteEnvironmentAreaSounds())
|
||||
{
|
||||
areaSoundEffectPlayed.consume();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onSoundEffectPlayed(SoundEffectPlayed soundEffectPlayed)
|
||||
{
|
||||
if (musicConfig.mutePrayerSounds()
|
||||
&& PRAYER_SOUNDS.contains(soundEffectPlayed.getSoundId()))
|
||||
{
|
||||
soundEffectPlayed.consume();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user