Merge remote-tracking branch 'runelite/master'

This commit is contained in:
Owain van Brakel
2020-04-18 23:38:58 +02:00
32 changed files with 812 additions and 280 deletions
+2 -2
View File
@@ -25,9 +25,9 @@
object ProjectVersions { object ProjectVersions {
const val launcherVersion = "2.2.0" const val launcherVersion = "2.2.0"
const val rlVersion = "1.6.10" const val rlVersion = "1.6.11"
const val openosrsVersion = "3.2.1" const val openosrsVersion = "3.2.2"
const val openosrsInjectorVersion = "1.0.3.1" const val openosrsInjectorVersion = "1.0.3.1"
const val rsversion = 189 const val rsversion = 189
@@ -29,6 +29,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.RuneLiteAPI;
import okhttp3.Call; import okhttp3.Call;
import okhttp3.Callback; import okhttp3.Callback;
@@ -77,8 +78,10 @@ public class ConfigClient
} }
} }
public void set(String key, String value) public CompletableFuture<Void> set(String key, String value)
{ {
CompletableFuture<Void> future = new CompletableFuture<>();
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
.addPathSegment("config") .addPathSegment("config")
.addPathSegment(key) .addPathSegment(key)
@@ -98,6 +101,7 @@ public class ConfigClient
public void onFailure(Call call, IOException e) public void onFailure(Call call, IOException e)
{ {
logger.warn("Unable to synchronize configuration item", e); logger.warn("Unable to synchronize configuration item", e);
future.completeExceptionally(e);
} }
@Override @Override
@@ -105,12 +109,17 @@ public class ConfigClient
{ {
response.close(); response.close();
logger.debug("Synchronized configuration value '{}' to '{}'", key, value); logger.debug("Synchronized configuration value '{}' to '{}'", key, value);
future.complete(null);
} }
}); });
return future;
} }
public void unset(String key) public CompletableFuture<Void> unset(String key)
{ {
CompletableFuture<Void> future = new CompletableFuture<>();
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
.addPathSegment("config") .addPathSegment("config")
.addPathSegment(key) .addPathSegment(key)
@@ -130,6 +139,7 @@ public class ConfigClient
public void onFailure(Call call, IOException e) public void onFailure(Call call, IOException e)
{ {
logger.warn("Unable to unset configuration item", e); logger.warn("Unable to unset configuration item", e);
future.completeExceptionally(e);
} }
@Override @Override
@@ -137,7 +147,10 @@ public class ConfigClient
{ {
response.close(); response.close();
logger.debug("Unset configuration value '{}'", key); logger.debug("Unset configuration value '{}'", key);
future.complete(null);
} }
}); });
return future;
} }
} }
@@ -33,6 +33,7 @@ import java.io.InputStreamReader;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.RuneLiteAPI;
@@ -52,8 +53,10 @@ public class LootTrackerClient
private final UUID uuid; private final UUID uuid;
public void submit(Collection<LootRecord> lootRecords) public CompletableFuture<Void> submit(Collection<LootRecord> lootRecords)
{ {
CompletableFuture<Void> future = new CompletableFuture<>();
HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() HttpUrl url = RuneLiteAPI.getApiBase().newBuilder()
.addPathSegment("loottracker") .addPathSegment("loottracker")
.build(); .build();
@@ -71,6 +74,7 @@ public class LootTrackerClient
public void onFailure(Call call, IOException e) public void onFailure(Call call, IOException e)
{ {
log.warn("unable to submit loot", e); log.warn("unable to submit loot", e);
future.completeExceptionally(e);
} }
@Override @Override
@@ -78,8 +82,11 @@ public class LootTrackerClient
{ {
log.debug("Submitted loot"); log.debug("Submitted loot");
response.close(); response.close();
future.complete(null);
} }
}); });
return future;
} }
public Collection<LootRecord> get() throws IOException public Collection<LootRecord> get() throws IOException
@@ -121,6 +121,10 @@ public final class AnimationID
public static final int FISHING_BAREHAND_CAUGHT_SWORDFISH_2 = 6708; public static final int FISHING_BAREHAND_CAUGHT_SWORDFISH_2 = 6708;
public static final int FISHING_BAREHAND_CAUGHT_TUNA_1 = 6710; public static final int FISHING_BAREHAND_CAUGHT_TUNA_1 = 6710;
public static final int FISHING_BAREHAND_CAUGHT_TUNA_2 = 6711; public static final int FISHING_BAREHAND_CAUGHT_TUNA_2 = 6711;
public static final int FISHING_PEARL_ROD = 8188;
public static final int FISHING_PEARL_FLY_ROD = 8189;
public static final int FISHING_PEARL_BARBARIAN_ROD = 8190;
public static final int FISHING_PEARL_OILY_ROD = 6932;
public static final int MINING_BRONZE_PICKAXE = 625; public static final int MINING_BRONZE_PICKAXE = 625;
public static final int MINING_IRON_PICKAXE = 626; public static final int MINING_IRON_PICKAXE = 626;
public static final int MINING_STEEL_PICKAXE = 627; public static final int MINING_STEEL_PICKAXE = 627;
@@ -138,6 +138,13 @@ public interface Client extends GameShell
*/ */
void setGameState(GameState gameState); void setGameState(GameState gameState);
/**
* Causes the client to shutdown. It is faster than
* {@link java.applet.Applet#stop()} because it doesn't wait for 4000ms.
* This will call {@link System#exit} when it is done
*/
void stopNow();
/** /**
* Gets the current logged in username. * Gets the current logged in username.
* *
@@ -11426,8 +11426,13 @@ public final class ItemID
public static final int CARROT = 24546; public static final int CARROT = 24546;
public static final int BROKEN_GOAT_HORN = 24547; public static final int BROKEN_GOAT_HORN = 24547;
public static final int CAKE_24549 = 24549; public static final int CAKE_24549 = 24549;
public static final int BLADE_OF_SAELDOR_I = 24551; public static final int BLADE_OF_SAELDOR_C = 24551;
public static final int BLADE_OF_SAELDOR_I_24553 = 24553; public static final int BLADE_OF_SAELDOR_C_24553 = 24553;
public static final int PYROMANCER_SET = 24554; public static final int PYROMANCER_SET = 24554;
public static final int TANGLEROOT_24555 = 24555;
public static final int TANGLEROOT_24557 = 24557;
public static final int TANGLEROOT_24559 = 24559;
public static final int TANGLEROOT_24561 = 24561;
public static final int TANGLEROOT_24563 = 24563;
/* This file is automatically generated. Do not edit. */ /* This file is automatically generated. Do not edit. */
} }
@@ -5993,7 +5993,6 @@ public final class NpcID
public static final int SISTER_SCAROPHIA = 6590; public static final int SISTER_SCAROPHIA = 6590;
public static final int LAVA_DRAGON = 6593; public static final int LAVA_DRAGON = 6593;
public static final int ENT = 6594; public static final int ENT = 6594;
public static final int THE_DISAPPOINTING_GELT = 6595;
public static final int ZOMBIE_6596 = 6596; public static final int ZOMBIE_6596 = 6596;
public static final int ZOMBIE_6597 = 6597; public static final int ZOMBIE_6597 = 6597;
public static final int ZOMBIE_6598 = 6598; public static final int ZOMBIE_6598 = 6598;
@@ -8483,21 +8482,17 @@ public final class NpcID
public static final int SISTER_SENGA = 9471; public static final int SISTER_SENGA = 9471;
public static final int SISTER_SENGA_9472 = 9472; public static final int SISTER_SENGA_9472 = 9472;
public static final int ENT_TRUNK = 9474; public static final int ENT_TRUNK = 9474;
public static final int DUKE_RABBACIO = 9475; public static final int TANGLEROOT_9492 = 9492;
public static final int PAWS = 9476; public static final int TANGLEROOT_9493 = 9493;
public static final int RABBIT_CHEF = 9477; public static final int TANGLEROOT_9494 = 9494;
public static final int GUARD_9478 = 9478; public static final int TANGLEROOT_9495 = 9495;
public static final int MAGIC_EGG = 9479; public static final int TANGLEROOT_9496 = 9496;
public static final int RABBIT_9480 = 9480; public static final int TANGLEROOT_9497 = 9497;
public static final int RABBIT_9481 = 9481; public static final int TANGLEROOT_9498 = 9498;
public static final int RABBIT_9482 = 9482; public static final int TANGLEROOT_9499 = 9499;
public static final int RID = 9483; public static final int TANGLEROOT_9500 = 9500;
public static final int FARMER_MAGGOT = 9484; public static final int TANGLEROOT_9501 = 9501;
public static final int FATHER_BUCKEREK = 9485; public static final int IORWERTH_WARRIOR_9502 = 9502;
public static final int RESTLESS_GOAT = 9486; public static final int IORWERTH_WARRIOR_9503 = 9503;
public static final int SHOP_KEEPER_9487 = 9487;
public static final int BARTENDER_9488 = 9488;
public static final int COW_CALF_9489 = 9489;
public static final int CHICKEN_9490 = 9490;
/* This file is automatically generated. Do not edit. */ /* This file is automatically generated. Do not edit. */
} }
@@ -12917,5 +12917,10 @@ public final class NullItemID
public static final int NULL_24548 = 24548; public static final int NULL_24548 = 24548;
public static final int NULL_24550 = 24550; public static final int NULL_24550 = 24550;
public static final int NULL_24552 = 24552; public static final int NULL_24552 = 24552;
public static final int NULL_24556 = 24556;
public static final int NULL_24558 = 24558;
public static final int NULL_24560 = 24560;
public static final int NULL_24562 = 24562;
public static final int NULL_24564 = 24564;
/* This file is automatically generated. Do not edit. */ /* This file is automatically generated. Do not edit. */
} }
@@ -14123,10 +14123,6 @@ public final class NullObjectID
public static final int NULL_30144 = 30144; public static final int NULL_30144 = 30144;
public static final int NULL_30156 = 30156; public static final int NULL_30156 = 30156;
public static final int NULL_30159 = 30159; public static final int NULL_30159 = 30159;
public static final int NULL_30165 = 30165;
public static final int NULL_30166 = 30166;
public static final int NULL_30167 = 30167;
public static final int NULL_30168 = 30168;
public static final int NULL_30171 = 30171; public static final int NULL_30171 = 30171;
public static final int NULL_30181 = 30181; public static final int NULL_30181 = 30181;
public static final int NULL_30182 = 30182; public static final int NULL_30182 = 30182;
@@ -14981,7 +14977,6 @@ public final class NullObjectID
public static final int NULL_31895 = 31895; public static final int NULL_31895 = 31895;
public static final int NULL_31896 = 31896; public static final int NULL_31896 = 31896;
public static final int NULL_31897 = 31897; public static final int NULL_31897 = 31897;
public static final int NULL_31899 = 31899;
public static final int NULL_31937 = 31937; public static final int NULL_31937 = 31937;
public static final int NULL_31938 = 31938; public static final int NULL_31938 = 31938;
public static final int NULL_31945 = 31945; public static final int NULL_31945 = 31945;
@@ -16166,7 +16161,6 @@ public final class NullObjectID
public static final int NULL_34678 = 34678; public static final int NULL_34678 = 34678;
public static final int NULL_34679 = 34679; public static final int NULL_34679 = 34679;
public static final int NULL_34680 = 34680; public static final int NULL_34680 = 34680;
public static final int NULL_34688 = 34688;
public static final int NULL_34689 = 34689; public static final int NULL_34689 = 34689;
public static final int NULL_34690 = 34690; public static final int NULL_34690 = 34690;
public static final int NULL_34691 = 34691; public static final int NULL_34691 = 34691;
@@ -18168,7 +18162,6 @@ public final class NullObjectID
public static final int NULL_37722 = 37722; public static final int NULL_37722 = 37722;
public static final int NULL_37723 = 37723; public static final int NULL_37723 = 37723;
public static final int NULL_37724 = 37724; public static final int NULL_37724 = 37724;
public static final int NULL_37725 = 37725;
public static final int NULL_37732 = 37732; public static final int NULL_37732 = 37732;
public static final int NULL_37733 = 37733; public static final int NULL_37733 = 37733;
public static final int NULL_37734 = 37734; public static final int NULL_37734 = 37734;
@@ -18336,11 +18329,7 @@ public final class NullObjectID
public static final int NULL_37933 = 37933; public static final int NULL_37933 = 37933;
public static final int NULL_37934 = 37934; public static final int NULL_37934 = 37934;
public static final int NULL_37935 = 37935; public static final int NULL_37935 = 37935;
public static final int NULL_37940 = 37940;
public static final int NULL_37945 = 37945;
public static final int NULL_37947 = 37947;
public static final int NULL_37950 = 37950; public static final int NULL_37950 = 37950;
public static final int NULL_37956 = 37956;
public static final int NULL_37958 = 37958; public static final int NULL_37958 = 37958;
/* This file is automatically generated. Do not edit. */ /* This file is automatically generated. Do not edit. */
} }
@@ -15803,8 +15803,6 @@ public final class ObjectID
public static final int POOL_OF_NIGHTMARES = 29706; public static final int POOL_OF_NIGHTMARES = 29706;
public static final int POOL_OF_NIGHTMARES_29707 = 29707; public static final int POOL_OF_NIGHTMARES_29707 = 29707;
public static final int SCOREBOARD_29708 = 29708; public static final int SCOREBOARD_29708 = 29708;
public static final int MAGIC_PORTAL_29711 = 29711;
public static final int PAINT_BUCKETS = 29712;
public static final int NOTICEBOARD_29718 = 29718; public static final int NOTICEBOARD_29718 = 29718;
public static final int BALLISTA_29719 = 29719; public static final int BALLISTA_29719 = 29719;
public static final int STAIRCASE_29720 = 29720; public static final int STAIRCASE_29720 = 29720;
@@ -16025,11 +16023,6 @@ public final class ObjectID
public static final int PAINTING_30155 = 30155; public static final int PAINTING_30155 = 30155;
public static final int FURNACE_30157 = 30157; public static final int FURNACE_30157 = 30157;
public static final int FURNACE_30158 = 30158; public static final int FURNACE_30158 = 30158;
public static final int BROKEN_EGG = 30160;
public static final int CONCH_SHELL = 30161;
public static final int THE_MAGIC_EGG = 30162;
public static final int CAKE = 30163;
public static final int CARROT = 30164;
public static final int CRACK_30169 = 30169; public static final int CRACK_30169 = 30169;
public static final int ROOT_30170 = 30170; public static final int ROOT_30170 = 30170;
public static final int PORTAL_30172 = 30172; public static final int PORTAL_30172 = 30172;
@@ -19545,9 +19538,6 @@ public final class ObjectID
public static final int NIGHTMARE_TOPIARY = 37630; public static final int NIGHTMARE_TOPIARY = 37630;
public static final int SUPPLIES_37631 = 37631; public static final int SUPPLIES_37631 = 37631;
public static final int BANNER_37726 = 37726; public static final int BANNER_37726 = 37726;
public static final int RABBIT = 37727;
public static final int RABBIT_37728 = 37728;
public static final int GRAVE_37729 = 37729;
public static final int ENERGY_BARRIER_37730 = 37730; public static final int ENERGY_BARRIER_37730 = 37730;
public static final int ENERGY_BARRIER_37731 = 37731; public static final int ENERGY_BARRIER_37731 = 37731;
public static final int SPORE = 37738; public static final int SPORE = 37738;
@@ -19590,19 +19580,8 @@ public final class ObjectID
public static final int CRATE_37936 = 37936; public static final int CRATE_37936 = 37936;
public static final int DOOR_37937 = 37937; public static final int DOOR_37937 = 37937;
public static final int DOOR_37938 = 37938; public static final int DOOR_37938 = 37938;
public static final int BROKEN_GOAT_HORN = 37939;
public static final int GATE_37941 = 37941;
public static final int GATE_37942 = 37942;
public static final int GATE_37943 = 37943;
public static final int GATE_37944 = 37944;
public static final int TREE_37946 = 37946;
public static final int DEAD_TREE_37948 = 37948;
public static final int SCOREBOARD_37949 = 37949; public static final int SCOREBOARD_37949 = 37949;
public static final int COFFIN_37951 = 37951; public static final int COFFIN_37951 = 37951;
public static final int JUNGLE_TREE_37952 = 37952;
public static final int YEW_37953 = 37953;
public static final int TREE_STUMP_37954 = 37954;
public static final int FURNACE_37955 = 37955;
public static final int HANDY_PORTAL = 37957; public static final int HANDY_PORTAL = 37957;
/* This file is automatically generated. Do not edit. */ /* This file is automatically generated. Do not edit. */
} }
@@ -308,4 +308,13 @@ public final class ScriptID
*/ */
@ScriptArguments(integer = 7) @ScriptArguments(integer = 7)
public static final int IGNORE_UPDATE = 630; public static final int IGNORE_UPDATE = 630;
/**
* Called in an onTimer, determines whether to layout the bank during a search
* <ul>
* <li> int (WidgetID) * 16, various widgets making up the bank interface </li>
* </ul>
*/
@ScriptArguments(integer = 16)
public static final int BANKMAIN_SEARCH_REFRESH = 283;
} }
@@ -27,10 +27,12 @@ package net.runelite.client;
import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Future;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.client.callback.ClientThread; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.ClientShutdown;
import net.runelite.client.task.Schedule; import net.runelite.client.task.Schedule;
@Singleton @Singleton
@@ -38,15 +40,23 @@ import net.runelite.client.task.Schedule;
public class ClientSessionManager public class ClientSessionManager
{ {
private final SessionClient sessionClient; private final SessionClient sessionClient;
private final ClientThread clientThread;
private UUID sessionId; private UUID sessionId;
@Inject @Inject
ClientSessionManager(ClientThread clientThread) ClientSessionManager(EventBus eventBus)
{ {
this.sessionClient = new SessionClient(); this.sessionClient = new SessionClient();
this.clientThread = clientThread;
eventBus.subscribe(ClientShutdown.class, this, (e) ->
{
Future<Void> f = shutdown();
if (f != null)
{
e.waitFor(f);
}
sessionId = null;
});
} }
void start() void start()
@@ -54,7 +64,8 @@ public class ClientSessionManager
sessionClient.openSession() sessionClient.openSession()
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(Schedulers.single()) .observeOn(Schedulers.single())
.subscribe(this::setUuid, this::error); .doOnError(this::error)
.subscribe(this::setUuid);
} }
@Schedule(period = 10, unit = ChronoUnit.MINUTES, asynchronous = true) @Schedule(period = 10, unit = ChronoUnit.MINUTES, asynchronous = true)
@@ -73,18 +84,15 @@ public class ClientSessionManager
.subscribe(); .subscribe();
} }
public void shutdown() private Future<Void> shutdown()
{ {
if (sessionId != null) if (sessionId != null)
{ {
sessionClient.delete(sessionId) return sessionClient.delete(sessionId)
.subscribeOn(Schedulers.io()) .toFuture();
.observeOn(Schedulers.single())
.doOnError(this::error)
.subscribe();
sessionId = null;
} }
return null;
} }
private void setUuid(UUID uuid) private void setUuid(UUID uuid)
@@ -469,7 +469,7 @@ public class RuneLite
// Initialize UI // Initialize UI
RuneLiteSplashScreen.stage(.80, "Initialize UI"); RuneLiteSplashScreen.stage(.80, "Initialize UI");
clientUI.init(this); clientUI.init();
// Initialize Discord service // Initialize Discord service
discordService.init(); discordService.init();
@@ -599,13 +599,6 @@ public class RuneLite
} }
} }
public void shutdown()
{
clientSessionManager.shutdown();
discordService.close();
groups.close();
}
private static class ConfigFileConverter implements ValueConverter<File> private static class ConfigFileConverter implements ValueConverter<File>
{ {
@Override @Override
@@ -371,18 +371,6 @@ public interface RuneLiteConfig extends Config
return false; return false;
} }
@ConfigItem(
keyName = "infoBoxWrap",
name = "Infobox wrap count",
description = "Configures the amount of infoboxes shown before wrapping",
position = 29,
titleSection = "infoboxTitle"
)
default int infoBoxWrap()
{
return 4;
}
@ConfigItem( @ConfigItem(
keyName = "infoBoxSize", keyName = "infoBoxSize",
name = "Infobox size", name = "Infobox size",
@@ -0,0 +1,73 @@
/*
* 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.client.events;
import java.time.Duration;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.events.Event;
@Value
@Slf4j
public class ClientShutdown implements Event
{
private Queue<Future<?>> tasks = new ConcurrentLinkedQueue<>();
public void waitFor(Future<?> future)
{
tasks.add(future);
}
public void waitForAllConsumers(Duration totalTimeout)
{
long deadline = System.nanoTime() + totalTimeout.toNanos();
for (Future<?> task; (task = tasks.poll()) != null; )
{
long timeout = deadline - System.nanoTime();
if (timeout < 0)
{
log.warn("Timed out waiting for task completion");
return;
}
try
{
task.get(timeout, TimeUnit.NANOSECONDS);
}
catch (ThreadDeath d)
{
throw d;
}
catch (Throwable t)
{
log.warn("Error during shutdown: ", t);
}
}
}
}
@@ -49,25 +49,52 @@ public class KeyManager
public void processKeyPressed(KeyEvent keyEvent) public void processKeyPressed(KeyEvent keyEvent)
{ {
if (keyEvent.isConsumed())
{
return;
}
for (KeyListener keyListener : keyListeners) for (KeyListener keyListener : keyListeners)
{ {
keyListener.keyPressed(keyEvent); keyListener.keyPressed(keyEvent);
if (keyEvent.isConsumed())
{
break;
}
} }
} }
public void processKeyReleased(KeyEvent keyEvent) public void processKeyReleased(KeyEvent keyEvent)
{ {
if (keyEvent.isConsumed())
{
return;
}
for (KeyListener keyListener : keyListeners) for (KeyListener keyListener : keyListeners)
{ {
keyListener.keyReleased(keyEvent); keyListener.keyReleased(keyEvent);
if (keyEvent.isConsumed())
{
break;
}
} }
} }
public void processKeyTyped(KeyEvent keyEvent) public void processKeyTyped(KeyEvent keyEvent)
{ {
if (keyEvent.isConsumed())
{
return;
}
for (KeyListener keyListener : keyListeners) for (KeyListener keyListener : keyListeners)
{ {
keyListener.keyTyped(keyEvent); keyListener.keyTyped(keyEvent);
if (keyEvent.isConsumed())
{
break;
}
} }
} }
} }
@@ -82,30 +82,57 @@ public class MouseManager
public MouseEvent processMousePressed(MouseEvent mouseEvent) public MouseEvent processMousePressed(MouseEvent mouseEvent)
{ {
if (mouseEvent.isConsumed())
{
return mouseEvent;
}
checkExtraMouseButtons(mouseEvent); checkExtraMouseButtons(mouseEvent);
for (MouseListener mouseListener : mouseListeners) for (MouseListener mouseListener : mouseListeners)
{ {
mouseEvent = mouseListener.mousePressed(mouseEvent); mouseEvent = mouseListener.mousePressed(mouseEvent);
if (mouseEvent.isConsumed())
{
break;
}
} }
return mouseEvent; return mouseEvent;
} }
public MouseEvent processMouseReleased(MouseEvent mouseEvent) public MouseEvent processMouseReleased(MouseEvent mouseEvent)
{ {
if (mouseEvent.isConsumed())
{
return mouseEvent;
}
checkExtraMouseButtons(mouseEvent); checkExtraMouseButtons(mouseEvent);
for (MouseListener mouseListener : mouseListeners) for (MouseListener mouseListener : mouseListeners)
{ {
mouseEvent = mouseListener.mouseReleased(mouseEvent); mouseEvent = mouseListener.mouseReleased(mouseEvent);
if (mouseEvent.isConsumed())
{
break;
}
} }
return mouseEvent; return mouseEvent;
} }
public MouseEvent processMouseClicked(MouseEvent mouseEvent) public MouseEvent processMouseClicked(MouseEvent mouseEvent)
{ {
if (mouseEvent.isConsumed())
{
return mouseEvent;
}
checkExtraMouseButtons(mouseEvent); checkExtraMouseButtons(mouseEvent);
for (MouseListener mouseListener : mouseListeners) for (MouseListener mouseListener : mouseListeners)
{ {
mouseEvent = mouseListener.mouseClicked(mouseEvent); mouseEvent = mouseListener.mouseClicked(mouseEvent);
if (mouseEvent.isConsumed())
{
break;
}
} }
return mouseEvent; return mouseEvent;
} }
@@ -123,45 +150,90 @@ public class MouseManager
public MouseEvent processMouseEntered(MouseEvent mouseEvent) public MouseEvent processMouseEntered(MouseEvent mouseEvent)
{ {
if (mouseEvent.isConsumed())
{
return mouseEvent;
}
for (MouseListener mouseListener : mouseListeners) for (MouseListener mouseListener : mouseListeners)
{ {
mouseEvent = mouseListener.mouseEntered(mouseEvent); mouseEvent = mouseListener.mouseEntered(mouseEvent);
if (mouseEvent.isConsumed())
{
break;
}
} }
return mouseEvent; return mouseEvent;
} }
public MouseEvent processMouseExited(MouseEvent mouseEvent) public MouseEvent processMouseExited(MouseEvent mouseEvent)
{ {
if (mouseEvent.isConsumed())
{
return mouseEvent;
}
for (MouseListener mouseListener : mouseListeners) for (MouseListener mouseListener : mouseListeners)
{ {
mouseEvent = mouseListener.mouseExited(mouseEvent); mouseEvent = mouseListener.mouseExited(mouseEvent);
if (mouseEvent.isConsumed())
{
break;
}
} }
return mouseEvent; return mouseEvent;
} }
public MouseEvent processMouseDragged(MouseEvent mouseEvent) public MouseEvent processMouseDragged(MouseEvent mouseEvent)
{ {
if (mouseEvent.isConsumed())
{
return mouseEvent;
}
for (MouseListener mouseListener : mouseListeners) for (MouseListener mouseListener : mouseListeners)
{ {
mouseEvent = mouseListener.mouseDragged(mouseEvent); mouseEvent = mouseListener.mouseDragged(mouseEvent);
if (mouseEvent.isConsumed())
{
break;
}
} }
return mouseEvent; return mouseEvent;
} }
public MouseEvent processMouseMoved(MouseEvent mouseEvent) public MouseEvent processMouseMoved(MouseEvent mouseEvent)
{ {
if (mouseEvent.isConsumed())
{
return mouseEvent;
}
for (MouseListener mouseListener : mouseListeners) for (MouseListener mouseListener : mouseListeners)
{ {
mouseEvent = mouseListener.mouseMoved(mouseEvent); mouseEvent = mouseListener.mouseMoved(mouseEvent);
if (mouseEvent.isConsumed())
{
break;
}
} }
return mouseEvent; return mouseEvent;
} }
public MouseWheelEvent processMouseWheelMoved(MouseWheelEvent mouseWheelEvent) public MouseWheelEvent processMouseWheelMoved(MouseWheelEvent mouseWheelEvent)
{ {
if (mouseWheelEvent.isConsumed())
{
return mouseWheelEvent;
}
for (MouseWheelListener mouseWheelListener : mouseWheelListeners) for (MouseWheelListener mouseWheelListener : mouseWheelListeners)
{ {
mouseWheelEvent = mouseWheelListener.mouseWheelMoved(mouseWheelEvent); mouseWheelEvent = mouseWheelListener.mouseWheelMoved(mouseWheelEvent);
if (mouseWheelEvent.isConsumed())
{
break;
}
} }
return mouseWheelEvent; return mouseWheelEvent;
} }
@@ -44,10 +44,13 @@ import java.awt.Toolkit;
import java.awt.TrayIcon; import java.awt.TrayIcon;
import java.awt.Window; import java.awt.Window;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.time.Duration;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider; import javax.inject.Provider;
@@ -72,7 +75,6 @@ import net.runelite.api.Point;
import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameStateChanged;
import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo; import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.RuneLite;
import net.runelite.client.RuneLiteProperties; import net.runelite.client.RuneLiteProperties;
import net.runelite.client.callback.ClientThread; import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
@@ -80,6 +82,7 @@ import net.runelite.client.config.ExpandResizeType;
import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.config.WarningOnExit; import net.runelite.client.config.WarningOnExit;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.ClientShutdown;
import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.ConfigChanged;
import net.runelite.client.events.NavigationButtonAdded; import net.runelite.client.events.NavigationButtonAdded;
import net.runelite.client.events.NavigationButtonRemoved; import net.runelite.client.events.NavigationButtonRemoved;
@@ -131,6 +134,7 @@ public class ClientUI
private final Applet client; private final Applet client;
private final ConfigManager configManager; private final ConfigManager configManager;
private final Provider<ClientThread> clientThreadProvider; private final Provider<ClientThread> clientThreadProvider;
private final EventBus eventBus;
private final CardLayout cardLayout = new CardLayout(); private final CardLayout cardLayout = new CardLayout();
private final Rectangle sidebarButtonPosition = new Rectangle(); private final Rectangle sidebarButtonPosition = new Rectangle();
private boolean withTitleBar; private boolean withTitleBar;
@@ -144,6 +148,7 @@ public class ClientUI
private NavigationButton sidebarNavigationButton; private NavigationButton sidebarNavigationButton;
private JButton sidebarNavigationJButton; private JButton sidebarNavigationJButton;
private Dimension lastClientSize; private Dimension lastClientSize;
private Cursor defaultCursor;
private Field opacityField; private Field opacityField;
private Field peerField; private Field peerField;
private Method setOpacityMethod; private Method setOpacityMethod;
@@ -164,6 +169,7 @@ public class ClientUI
this.client = client; this.client = client;
this.configManager = configManager; this.configManager = configManager;
this.clientThreadProvider = clientThreadProvider; this.clientThreadProvider = clientThreadProvider;
this.eventBus = eventbus;
eventbus.subscribe(ConfigChanged.class, this, this::onConfigChanged); eventbus.subscribe(ConfigChanged.class, this, this::onConfigChanged);
eventbus.subscribe(NavigationButtonAdded.class, this, this::onNavigationButtonAdded); eventbus.subscribe(NavigationButtonAdded.class, this, this::onNavigationButtonAdded);
@@ -313,11 +319,8 @@ public class ClientUI
/** /**
* Initialize UI. * Initialize UI.
*
* @param runelite runelite instance that will be shut down on exit
* @throws Exception exception that can occur during creation of the UI
*/ */
public void init(final RuneLite runelite) throws Exception public void init() throws Exception
{ {
SwingUtilities.invokeAndWait(() -> SwingUtilities.invokeAndWait(() ->
{ {
@@ -335,14 +338,36 @@ public class ClientUI
frame.setLocationRelativeTo(frame.getOwner()); frame.setLocationRelativeTo(frame.getOwner());
frame.setResizable(true); frame.setResizable(true);
SwingUtil.addGracefulExitCallback(frame, frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
() -> frame.addWindowListener(new WindowAdapter()
{ {
saveClientBoundsConfig(); @Override
runelite.shutdown(); public void windowClosing(WindowEvent event)
}, {
this::showWarningOnExit int result = JOptionPane.OK_OPTION;
);
if (showWarningOnExit())
{
try
{
result = JOptionPane.showConfirmDialog(
frame,
"Are you sure you want to exit?", "Exit",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
}
catch (Exception e)
{
log.warn("Unexpected exception occurred while check for confirm required", e);
}
}
if (result == JOptionPane.OK_OPTION)
{
shutdownClient();
}
}
});
container = new JPanel(); container = new JPanel();
container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS)); container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
@@ -550,7 +575,7 @@ public class ClientUI
SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(frame, SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(frame,
"OpenOSRS has not yet been updated to work with the latest\n" "OpenOSRS has not yet been updated to work with the latest\n"
+ "game update, it will work with reduced functionality until then.", + "game update, it will work with reduced functionality until then.",
"RuneLite is outdated", INFORMATION_MESSAGE)); "OpenOSRS is outdated", INFORMATION_MESSAGE));
} }
} }
@@ -569,6 +594,45 @@ public class ClientUI
return false; return false;
} }
private void shutdownClient()
{
saveClientBoundsConfig();
ClientShutdown csev = new ClientShutdown();
eventBus.post(ClientShutdown.class, csev);
new Thread(() ->
{
csev.waitForAllConsumers(Duration.ofSeconds(10));
if (client != null)
{
// The client can call System.exit when it's done shutting down
// if it doesn't though, we want to exit anyway, so race it
int clientShutdownWaitMS;
if (client instanceof Client)
{
((Client) client).stopNow();
clientShutdownWaitMS = 1000;
}
else
{
// it will continue rendering for about 4 seconds before attempting shutdown if its vanilla
client.stop();
frame.setVisible(false);
clientShutdownWaitMS = 6000;
}
try
{
Thread.sleep(clientShutdownWaitMS);
}
catch (InterruptedException ignored)
{
}
}
System.exit(0);
}, "OpenOSRS Shutdown").start();
}
/** /**
* Paint this component to target graphics * Paint this component to target graphics
* *
@@ -654,7 +718,27 @@ public class ClientUI
} }
/** /**
* Changes cursor for client window. Requires ${@link ClientUI#init(RuneLite)} to be called first. * Returns current cursor set on game container
*
* @return awt cursor
*/
public Cursor getCurrentCursor()
{
return container.getCursor();
}
/**
* Returns current custom cursor or default system cursor if cursor is not set
*
* @return awt cursor
*/
public Cursor getDefaultCursor()
{
return defaultCursor != null ? defaultCursor : Cursor.getDefaultCursor();
}
/**
* Changes cursor for client window. Requires ${@link ClientUI#init()} to be called first.
* FIXME: This is working properly only on Windows, Linux and Mac are displaying cursor incorrectly * FIXME: This is working properly only on Windows, Linux and Mac are displaying cursor incorrectly
* *
* @param image cursor image * @param image cursor image
@@ -669,7 +753,18 @@ public class ClientUI
final java.awt.Point hotspot = new java.awt.Point(0, 0); final java.awt.Point hotspot = new java.awt.Point(0, 0);
final Cursor cursorAwt = Toolkit.getDefaultToolkit().createCustomCursor(image, hotspot, name); final Cursor cursorAwt = Toolkit.getDefaultToolkit().createCustomCursor(image, hotspot, name);
container.setCursor(cursorAwt); defaultCursor = cursorAwt;
setCursor(cursorAwt);
}
/**
* Changes cursor for client window. Requires ${@link ClientUI#init()} to be called first.
*
* @param cursor awt cursor
*/
public void setCursor(final Cursor cursor)
{
container.setCursor(cursor);
} }
/** /**
@@ -684,6 +779,7 @@ public class ClientUI
return; return;
} }
defaultCursor = null;
container.setCursor(Cursor.getDefaultCursor()); container.setCursor(Cursor.getDefaultCursor());
} }
@@ -128,6 +128,12 @@ public class FlatTextField extends JPanel
setBackground(color, true); setBackground(color, true);
} }
@Override
public boolean requestFocusInWindow()
{
return textField.requestFocusInWindow();
}
public void setBackground(Color color, boolean saveColor) public void setBackground(Color color, boolean saveColor)
{ {
if (color == null) if (color == null)
@@ -49,6 +49,7 @@ public abstract class Overlay implements LayoutableRenderableEntity
private OverlayPriority priority = OverlayPriority.NONE; private OverlayPriority priority = OverlayPriority.NONE;
private OverlayLayer layer = OverlayLayer.UNDER_WIDGETS; private OverlayLayer layer = OverlayLayer.UNDER_WIDGETS;
private final List<OverlayMenuEntry> menuEntries = new ArrayList<>(); private final List<OverlayMenuEntry> menuEntries = new ArrayList<>();
private boolean resizable;
protected Overlay() protected Overlay()
{ {
@@ -261,7 +261,7 @@ public class OverlayManager
saveOverlay(overlay); saveOverlay(overlay);
} }
private synchronized void rebuildOverlayLayers() synchronized void rebuildOverlayLayers()
{ {
for (OverlayLayer l : OverlayLayer.values()) for (OverlayLayer l : OverlayLayer.values())
{ {
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* 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.ui.overlay;
import java.awt.Dimension;
import java.awt.Graphics2D;
import lombok.Getter;
import lombok.Setter;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.components.ComponentConstants;
import net.runelite.client.ui.overlay.components.PanelComponent;
@Getter
@Setter
public abstract class OverlayPanel extends Overlay
{
protected final PanelComponent panelComponent = new PanelComponent();
/**
* Enables/disables automatic clearing of {@link this#getPanelComponent()} children after rendering (enabled by default)
*/
private boolean clearChildren = true;
/**
* Enables/disables automatic font size changes based on panel component size relative to default panel component size.
*/
private boolean dynamicFont = false;
protected OverlayPanel()
{
super();
setResizable(true);
}
protected OverlayPanel(Plugin plugin)
{
super(plugin);
setResizable(true);
}
@Override
public Dimension render(final Graphics2D graphics)
{
final Dimension oldSize = panelComponent.getPreferredSize();
if (getPreferredSize() != null)
{
panelComponent.setPreferredSize(getPreferredSize());
if (dynamicFont)
{
if (getPreferredSize().width >= ComponentConstants.STANDARD_WIDTH * 1.3)
{
graphics.setFont(FontManager.getRunescapeBoldFont());
}
else if (getPreferredSize().width <= ComponentConstants.STANDARD_WIDTH * 0.8)
{
graphics.setFont(FontManager.getRunescapeSmallFont());
}
}
}
final Dimension dimension = panelComponent.render(graphics);
if (clearChildren)
{
panelComponent.getChildren().clear();
}
panelComponent.setPreferredSize(oldSize);
return dimension;
}
}
@@ -25,8 +25,10 @@
package net.runelite.client.ui.overlay; package net.runelite.client.ui.overlay;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.primitives.Ints;
import java.awt.Color; import java.awt.Color;
import java.awt.Composite; import java.awt.Composite;
import java.awt.Cursor;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Paint; import java.awt.Paint;
@@ -60,6 +62,7 @@ import net.runelite.client.input.KeyListener;
import net.runelite.client.input.KeyManager; import net.runelite.client.input.KeyManager;
import net.runelite.client.input.MouseAdapter; import net.runelite.client.input.MouseAdapter;
import net.runelite.client.input.MouseManager; import net.runelite.client.input.MouseManager;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.JagexColors; import net.runelite.client.ui.JagexColors;
import net.runelite.client.util.ColorUtil; import net.runelite.client.util.ColorUtil;
import net.runelite.client.util.MiscUtils; import net.runelite.client.util.MiscUtils;
@@ -71,21 +74,29 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
private static final int BORDER = 5; private static final int BORDER = 5;
private static final int BORDER_TOP = BORDER + 15; private static final int BORDER_TOP = BORDER + 15;
private static final int PADDING = 2; private static final int PADDING = 2;
private static final int MIN_OVERLAY_SIZE = 32;
private static final int OVERLAY_RESIZE_TOLERANCE = 5;
private static final Dimension SNAP_CORNER_SIZE = new Dimension(80, 80); private static final Dimension SNAP_CORNER_SIZE = new Dimension(80, 80);
private static final Color SNAP_CORNER_COLOR = new Color(0, 255, 255, 50); private static final Color SNAP_CORNER_COLOR = new Color(0, 255, 255, 50);
private static final Color SNAP_CORNER_ACTIVE_COLOR = new Color(0, 255, 0, 100); private static final Color SNAP_CORNER_ACTIVE_COLOR = new Color(0, 255, 0, 100);
private static final Color MOVING_OVERLAY_COLOR = new Color(255, 255, 0, 100); private static final Color MOVING_OVERLAY_COLOR = new Color(255, 255, 0, 100);
private static final Color MOVING_OVERLAY_ACTIVE_COLOR = new Color(255, 255, 0, 200); private static final Color MOVING_OVERLAY_ACTIVE_COLOR = new Color(255, 255, 0, 200);
private static final Color MOVING_OVERLAY_RESIZING_COLOR = new Color(255, 0, 255, 200);
private final Client client; private final Client client;
private final OverlayManager overlayManager; private final OverlayManager overlayManager;
private final RuneLiteConfig runeLiteConfig; private final RuneLiteConfig runeLiteConfig;
private final ClientUI clientUI;
// Overlay movement variables // Overlay movement variables
private final Point overlayOffset = new Point(); private final Point overlayOffset = new Point();
private final Point mousePosition = new Point(); private final Point mousePosition = new Point();
private Overlay movedOverlay; private Overlay currentManagedOverlay;
private Rectangle currentManagedBounds;
private boolean inOverlayManagingMode;
private boolean inOverlayResizingMode;
private boolean inOverlayDraggingMode; private boolean inOverlayDraggingMode;
private boolean inMenuEntryMode; private boolean inMenuEntryMode;
private boolean startedMovingOverlay;
private MenuEntry[] menuEntries; private MenuEntry[] menuEntries;
// Overlay state validation // Overlay state validation
@@ -106,11 +117,13 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
final RuneLiteConfig runeLiteConfig, final RuneLiteConfig runeLiteConfig,
final MouseManager mouseManager, final MouseManager mouseManager,
final KeyManager keyManager, final KeyManager keyManager,
final EventBus eventbus) final EventBus eventbus,
final ClientUI clientUI)
{ {
this.client = client; this.client = client;
this.overlayManager = overlayManager; this.overlayManager = overlayManager;
this.runeLiteConfig = runeLiteConfig; this.runeLiteConfig = runeLiteConfig;
this.clientUI = clientUI;
keyManager.registerKeyListener(this); keyManager.registerKeyListener(this);
mouseManager.registerMouseListener(this); mouseManager.registerMouseListener(this);
@@ -123,7 +136,8 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
{ {
if (!event.isFocused()) if (!event.isFocused())
{ {
inOverlayDraggingMode = false; inOverlayManagingMode = false;
resetOverlayManagementMode();
inMenuEntryMode = false; inMenuEntryMode = false;
menuEntries = null; menuEntries = null;
} }
@@ -202,7 +216,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
OverlayUtil.setGraphicProperties(graphics); OverlayUtil.setGraphicProperties(graphics);
// Draw snap corners // Draw snap corners
if (layer == OverlayLayer.UNDER_WIDGETS && movedOverlay != null && movedOverlay.getPosition() != OverlayPosition.DETACHED) if (inOverlayDraggingMode && layer == OverlayLayer.UNDER_WIDGETS && currentManagedOverlay != null && currentManagedOverlay.getPosition() != OverlayPosition.DETACHED)
{ {
final OverlayBounds translatedSnapCorners = snapCorners.translated( final OverlayBounds translatedSnapCorners = snapCorners.translated(
-SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.width,
@@ -294,12 +308,19 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
if (!bounds.isEmpty()) if (!bounds.isEmpty())
{ {
if (inOverlayDraggingMode) if (inOverlayManagingMode)
{ {
final Color previous = graphics.getColor(); if (inOverlayResizingMode && currentManagedOverlay == overlay)
graphics.setColor(movedOverlay == overlay ? MOVING_OVERLAY_ACTIVE_COLOR : MOVING_OVERLAY_COLOR); {
graphics.setColor(MOVING_OVERLAY_RESIZING_COLOR);
}
else
{
graphics.setColor(inOverlayDraggingMode && currentManagedOverlay == overlay ? MOVING_OVERLAY_ACTIVE_COLOR : MOVING_OVERLAY_COLOR);
}
graphics.draw(bounds); graphics.draw(bounds);
graphics.setColor(previous); graphics.setPaint(paint);
} }
if (!client.isMenuOpen() && !client.isSpellSelected() && bounds.contains(mouse)) if (!client.isMenuOpen() && !client.isSpellSelected() && bounds.contains(mouse))
@@ -319,7 +340,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
@Override @Override
public MouseEvent mousePressed(MouseEvent mouseEvent) public MouseEvent mousePressed(MouseEvent mouseEvent)
{ {
if (!inOverlayDraggingMode) if (!inOverlayManagingMode)
{ {
return mouseEvent; return mouseEvent;
} }
@@ -327,41 +348,104 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
final Point mousePoint = mouseEvent.getPoint(); final Point mousePoint = mouseEvent.getPoint();
mousePosition.setLocation(mousePoint); mousePosition.setLocation(mousePoint);
if (currentManagedOverlay == null)
{
return mouseEvent;
}
if (SwingUtilities.isRightMouseButton(mouseEvent))
{
overlayManager.resetOverlay(currentManagedOverlay);
}
else if (SwingUtilities.isLeftMouseButton(mouseEvent))
{
final Point offset = new Point(mousePoint.x, mousePoint.y);
offset.translate(-currentManagedOverlay.getBounds().x, -currentManagedOverlay.getBounds().y);
overlayOffset.setLocation(offset);
inOverlayResizingMode = currentManagedOverlay != null && currentManagedOverlay.isResizable() && clientUI.getCurrentCursor() != clientUI.getDefaultCursor();
inOverlayDraggingMode = !inOverlayResizingMode;
startedMovingOverlay = true;
currentManagedBounds = new Rectangle(currentManagedOverlay.getBounds());
}
else
{
return mouseEvent;
}
mouseEvent.consume();
return mouseEvent;
}
@Override
public MouseEvent mouseMoved(MouseEvent mouseEvent)
{
if (!inOverlayManagingMode)
{
return mouseEvent;
}
final Point mousePoint = mouseEvent.getPoint();
mousePosition.setLocation(mousePoint);
if (!inOverlayResizingMode && !inOverlayDraggingMode)
{
currentManagedOverlay = null;
synchronized (overlayManager) synchronized (overlayManager)
{ {
for (Overlay overlay : overlayManager.getOverlays()) for (Overlay overlay : overlayManager.getOverlays())
{ {
final OverlayPosition overlayPosition = getCorrectedOverlayPosition(overlay); final Rectangle bounds = overlay.getBounds();
if (bounds.contains(mousePoint))
if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP)
{ {
continue; currentManagedOverlay = overlay;
}
if (overlay.getBounds().contains(mousePoint))
{
if (SwingUtilities.isRightMouseButton(mouseEvent))
{
overlayManager.resetOverlay(overlay);
}
else
{
final Point offset = new Point(mousePoint.x, mousePoint.y);
offset.translate(-overlay.getBounds().x, -overlay.getBounds().y);
overlayOffset.setLocation(offset);
mousePoint.translate(-offset.x, -offset.y);
movedOverlay = overlay;
movedOverlay.setPreferredPosition(null);
movedOverlay.setPreferredLocation(mousePoint);
overlayManager.saveOverlay(movedOverlay);
}
mouseEvent.consume();
break; break;
} }
} }
} }
}
if (currentManagedOverlay == null || !currentManagedOverlay.isResizable())
{
clientUI.setCursor(clientUI.getDefaultCursor());
return mouseEvent;
}
final Rectangle toleranceRect = new Rectangle(currentManagedOverlay.getBounds());
toleranceRect.grow(-OVERLAY_RESIZE_TOLERANCE, -OVERLAY_RESIZE_TOLERANCE);
final int outcode = toleranceRect.outcode(mouseEvent.getPoint());
switch (outcode)
{
case Rectangle.OUT_TOP:
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
break;
case Rectangle.OUT_TOP | Rectangle.OUT_LEFT:
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
break;
case Rectangle.OUT_LEFT:
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
break;
case Rectangle.OUT_LEFT | Rectangle.OUT_BOTTOM:
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
break;
case Rectangle.OUT_BOTTOM:
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
break;
case Rectangle.OUT_BOTTOM | Rectangle.OUT_RIGHT:
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
break;
case Rectangle.OUT_RIGHT:
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
break;
case Rectangle.OUT_RIGHT | Rectangle.OUT_TOP:
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
break;
default:
// center
clientUI.setCursor(clientUI.getDefaultCursor());
}
return mouseEvent; return mouseEvent;
} }
@@ -369,29 +453,100 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
@Override @Override
public MouseEvent mouseDragged(MouseEvent mouseEvent) public MouseEvent mouseDragged(MouseEvent mouseEvent)
{ {
if (!inOverlayDraggingMode) if (!inOverlayManagingMode)
{
return mouseEvent;
}
final Point p = mouseEvent.getPoint();
mousePosition.setLocation(p);
if (currentManagedOverlay == null)
{ {
return mouseEvent; return mouseEvent;
} }
final Point mousePoint = mouseEvent.getPoint();
mousePosition.setLocation(mousePoint);
final Rectangle canvasRect = new Rectangle(client.getRealDimensions()); final Rectangle canvasRect = new Rectangle(client.getRealDimensions());
if (!canvasRect.contains(mousePoint)) if (!canvasRect.contains(p))
{ {
return mouseEvent; return mouseEvent;
} }
if (movedOverlay != null) if (inOverlayResizingMode)
{
final Rectangle r = currentManagedBounds;
final int dx = p.x - r.x;
final int dy = p.y - r.y;
switch (clientUI.getCurrentCursor().getType())
{
case Cursor.N_RESIZE_CURSOR:
int height = r.height - dy;
r.setRect(r.x, r.y + dy, r.width, height);
break;
case Cursor.NW_RESIZE_CURSOR:
int width = r.width - dx;
height = r.height - dy;
r.setRect(r.x + dx, r.y + dy, width, height);
break;
case Cursor.W_RESIZE_CURSOR:
width = r.width - dx;
r.setRect(r.x + dx, r.y, width, r.height);
break;
case Cursor.SW_RESIZE_CURSOR:
width = r.width - dx;
height = dy;
r.setRect(r.x + dx, r.y, width, height);
break;
case Cursor.S_RESIZE_CURSOR:
height = dy;
r.setRect(r.x, r.y, r.width, height);
break;
case Cursor.SE_RESIZE_CURSOR:
width = dx;
height = dy;
r.setRect(r.x, r.y, width, height);
break;
case Cursor.E_RESIZE_CURSOR:
width = dx;
r.setRect(r.x, r.y, width, r.height);
break;
case Cursor.NE_RESIZE_CURSOR:
width = dx;
height = r.height - dy;
r.setRect(r.x, r.y + dy, width, height);
break;
default:
// center
}
currentManagedOverlay.setPreferredSize(new Dimension(Math.max(MIN_OVERLAY_SIZE, currentManagedBounds.width), Math.max(MIN_OVERLAY_SIZE, currentManagedBounds.height)));
if (currentManagedOverlay.getPreferredLocation() != null)
{
currentManagedOverlay.setPreferredLocation(currentManagedBounds.getLocation());
}
}
else if (inOverlayDraggingMode)
{ {
final Dimension realDimension = client.getRealDimensions(); final Dimension realDimension = client.getRealDimensions();
mousePoint.translate(-overlayOffset.x, -overlayOffset.y); p.translate(-overlayOffset.x, -overlayOffset.y);
mousePoint.x = MiscUtils.clamp(mousePoint.x, 0, Math.max(0, realDimension.width - movedOverlay.getBounds().width)); p.x = Ints.constrainToRange(p.x, 0, Math.max(0, realDimension.width - currentManagedOverlay.getBounds().width));
mousePoint.y = MiscUtils.clamp(mousePoint.y, 0, Math.max(0, realDimension.height - movedOverlay.getBounds().height)); p.y = Ints.constrainToRange(p.y, 0, Math.max(0, realDimension.height - currentManagedOverlay.getBounds().height));
movedOverlay.setPreferredPosition(null); currentManagedOverlay.setPreferredPosition(null);
movedOverlay.setPreferredLocation(mousePoint); currentManagedOverlay.setPreferredLocation(p);
mouseEvent.consume(); }
else
{
return mouseEvent;
}
if (startedMovingOverlay)
{
// Move currently moved overlay to correct layer
overlayManager.rebuildOverlayLayers();
startedMovingOverlay = false;
} }
return mouseEvent; return mouseEvent;
@@ -400,12 +555,15 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
@Override @Override
public MouseEvent mouseReleased(MouseEvent mouseEvent) public MouseEvent mouseReleased(MouseEvent mouseEvent)
{ {
if (movedOverlay != null) if (!inOverlayManagingMode || currentManagedOverlay == null || (!inOverlayDraggingMode && !inOverlayResizingMode))
{ {
return mouseEvent;
}
mousePosition.setLocation(-1, -1); mousePosition.setLocation(-1, -1);
// do not snapcorner detached overlays // do not snapcorner detached overlays
if (movedOverlay.getPosition() != OverlayPosition.DETACHED) if (currentManagedOverlay.getPosition() != OverlayPosition.DETACHED && inOverlayDraggingMode)
{ {
final OverlayBounds snapCorners = this.snapCorners.translated(-SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height); final OverlayBounds snapCorners = this.snapCorners.translated(-SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height);
@@ -415,24 +573,22 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
{ {
OverlayPosition position = snapCorners.fromBounds(snapCorner); OverlayPosition position = snapCorners.fromBounds(snapCorner);
if (position == movedOverlay.getPosition()) if (position == currentManagedOverlay.getPosition())
{ {
// overlay moves back to default position // overlay moves back to default position
position = null; position = null;
} }
movedOverlay.setPreferredPosition(position); currentManagedOverlay.setPreferredPosition(position);
movedOverlay.setPreferredLocation(null); // from dragging currentManagedOverlay.setPreferredLocation(null); // from dragging
break; break;
} }
} }
} }
overlayManager.saveOverlay(movedOverlay); overlayManager.saveOverlay(currentManagedOverlay);
movedOverlay = null; resetOverlayManagementMode();
mouseEvent.consume(); mouseEvent.consume();
}
return mouseEvent; return mouseEvent;
} }
@@ -446,7 +602,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
{ {
if (e.isAltDown()) if (e.isAltDown())
{ {
inOverlayDraggingMode = true; inOverlayManagingMode = true;
} }
if (e.isShiftDown() && runeLiteConfig.menuEntryShift()) if (e.isShiftDown() && runeLiteConfig.menuEntryShift())
@@ -460,7 +616,8 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
{ {
if (!e.isAltDown()) if (!e.isAltDown())
{ {
inOverlayDraggingMode = false; inOverlayManagingMode = false;
resetOverlayManagementMode();
} }
if (!e.isShiftDown()) if (!e.isShiftDown())
@@ -546,6 +703,15 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
return overlayPosition; return overlayPosition;
} }
private void resetOverlayManagementMode()
{
inOverlayResizingMode = false;
inOverlayDraggingMode = false;
currentManagedOverlay = null;
currentManagedBounds = null;
clientUI.setCursor(clientUI.getDefaultCursor());
}
private boolean shouldInvalidateBounds() private boolean shouldInvalidateBounds()
{ {
final Widget chatbox = client.getWidget(WidgetInfo.CHATBOX); final Widget chatbox = client.getWidget(WidgetInfo.CHATBOX);
@@ -45,6 +45,7 @@ public class PanelComponent implements LayoutableRenderableEntity
private Point preferredLocation = new Point(); private Point preferredLocation = new Point();
@Setter @Setter
@Getter
private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0); private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0);
@Setter @Setter
@@ -58,7 +59,7 @@ public class PanelComponent implements LayoutableRenderableEntity
private ComponentOrientation orientation = ComponentOrientation.VERTICAL; private ComponentOrientation orientation = ComponentOrientation.VERTICAL;
@Setter @Setter
private int wrapping = -1; private boolean wrap = false;
@Setter @Setter
private Rectangle border = new Rectangle( private Rectangle border = new Rectangle(
@@ -114,12 +115,23 @@ public class PanelComponent implements LayoutableRenderableEntity
int totalWidth = 0; int totalWidth = 0;
// Render all children // Render all children
for (int i = 0; i < children.size(); i++) for (final LayoutableRenderableEntity child : children)
{ {
final LayoutableRenderableEntity child = children.get(i); // Correctly propagate child dimensions based on orientation and wrapping
if (!wrap)
{
switch (orientation)
{
case VERTICAL:
child.setPreferredSize(new Dimension(childPreferredSize.width, 0));
break;
case HORIZONTAL:
child.setPreferredSize(new Dimension(0, childPreferredSize.height));
break;
}
}
child.setPreferredLocation(new Point(x, y)); child.setPreferredLocation(new Point(x, y));
child.setPreferredSize(childPreferredSize);
final Dimension childDimension = child.render(graphics); final Dimension childDimension = child.render(graphics);
switch (orientation) switch (orientation)
@@ -140,28 +152,38 @@ public class PanelComponent implements LayoutableRenderableEntity
totalWidth = Math.max(totalWidth, width); totalWidth = Math.max(totalWidth, width);
totalHeight = Math.max(totalHeight, height); totalHeight = Math.max(totalHeight, height);
if (wrapping > 0 && i < children.size() - 1 && (i + 1) % wrapping == 0) if (!wrap)
{ {
continue;
}
switch (orientation) switch (orientation)
{ {
case VERTICAL: case VERTICAL:
{
if (childPreferredSize.height > 0 && height >= childPreferredSize.height)
{ {
height = 0; height = 0;
y = baseY; y = baseY;
int diff = childDimension.width + gap.x; int diff = childDimension.width + gap.x;
x += diff; x += diff;
width += diff; width += diff;
}
break; break;
} }
case HORIZONTAL: case HORIZONTAL:
{
if (childPreferredSize.width > 0 && width >= childPreferredSize.width)
{ {
width = 0; width = 0;
x = baseX; x = baseX;
int diff = childDimension.height + gap.y; int diff = childDimension.height + gap.y;
y += diff; y += diff;
height += diff; height += diff;
break;
} }
break;
} }
} }
} }
@@ -36,19 +36,20 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPanel;
import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.ComponentOrientation; import net.runelite.client.ui.overlay.components.ComponentOrientation;
import net.runelite.client.ui.overlay.components.InfoBoxComponent; import net.runelite.client.ui.overlay.components.InfoBoxComponent;
import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity; import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.tooltip.Tooltip; import net.runelite.client.ui.overlay.tooltip.Tooltip;
import net.runelite.client.ui.overlay.tooltip.TooltipManager; import net.runelite.client.ui.overlay.tooltip.TooltipManager;
@Singleton @Singleton
public class InfoBoxOverlay extends Overlay public class InfoBoxOverlay extends OverlayPanel
{ {
private final PanelComponent panelComponent = new PanelComponent(); private static final int GAP = 1;
private static final int DEFAULT_WRAP_COUNT = 4;
private final InfoBoxManager infoboxManager; private final InfoBoxManager infoboxManager;
private final TooltipManager tooltipManager; private final TooltipManager tooltipManager;
private final Client client; private final Client client;
@@ -66,10 +67,12 @@ public class InfoBoxOverlay extends Overlay
this.client = client; this.client = client;
this.config = config; this.config = config;
setPosition(OverlayPosition.TOP_LEFT); setPosition(OverlayPosition.TOP_LEFT);
setClearChildren(false);
panelComponent.setWrap(true);
panelComponent.setBackgroundColor(null); panelComponent.setBackgroundColor(null);
panelComponent.setBorder(new Rectangle()); panelComponent.setBorder(new Rectangle());
panelComponent.setGap(new Point(1, 1)); panelComponent.setGap(new Point(GAP, GAP));
} }
@Override @Override
@@ -82,12 +85,12 @@ public class InfoBoxOverlay extends Overlay
return null; return null;
} }
panelComponent.getChildren().clear(); // Set preferred size to the size of DEFAULT_WRAP_COUNT infoboxes, including the padding - which is applied
panelComponent.setWrapping(config.infoBoxWrap()); // to the last infobox prior to wrapping too.
panelComponent.setPreferredSize(new Dimension(DEFAULT_WRAP_COUNT * (config.infoBoxSize() + GAP), DEFAULT_WRAP_COUNT * (config.infoBoxSize() + GAP)));
panelComponent.setOrientation(config.infoBoxVertical() panelComponent.setOrientation(config.infoBoxVertical()
? ComponentOrientation.VERTICAL ? ComponentOrientation.VERTICAL
: ComponentOrientation.HORIZONTAL); : ComponentOrientation.HORIZONTAL);
panelComponent.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize()));
for (InfoBox box : infoBoxes) for (InfoBox box : infoBoxes)
{ {
@@ -107,10 +110,11 @@ public class InfoBoxOverlay extends Overlay
} }
infoBoxComponent.setImage(box.getScaledImage()); infoBoxComponent.setImage(box.getScaledImage());
infoBoxComponent.setTooltip(box.getTooltip()); infoBoxComponent.setTooltip(box.getTooltip());
infoBoxComponent.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize()));
panelComponent.getChildren().add(infoBoxComponent); panelComponent.getChildren().add(infoBoxComponent);
} }
final Dimension dimension = panelComponent.render(graphics); final Dimension dimension = super.render(graphics);
// Handle tooltips // Handle tooltips
final Point mouse = new Point(client.getMouseCanvasPosition().getX(), client.getMouseCanvasPosition().getY()); final Point mouse = new Point(client.getMouseCanvasPosition().getX(), client.getMouseCanvasPosition().getY());
@@ -135,6 +139,7 @@ public class InfoBoxOverlay extends Overlay
} }
} }
panelComponent.getChildren().clear();
return dimension; return dimension;
} }
} }
@@ -24,27 +24,14 @@
*/ */
package net.runelite.client.ui.overlay.tooltip; package net.runelite.client.ui.overlay.tooltip;
import com.google.common.base.Strings;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.Getter; import lombok.Getter;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
@Singleton @Singleton
public class TooltipManager public class TooltipManager
{ {
private final ConfigManager configManager;
@Inject
private TooltipManager(final ConfigManager configManager)
{
this.configManager = configManager;
}
@Getter @Getter
private final List<Tooltip> tooltips = new ArrayList<>(); private final List<Tooltip> tooltips = new ArrayList<>();
@@ -62,17 +49,4 @@ public class TooltipManager
{ {
tooltips.clear(); tooltips.clear();
} }
@Subscribe
public void onConfigChanged(final ConfigChanged event)
{
// Temporary fix for resetting repositioned tooltip overlay
// TODO: Remove this eventually
if (event.getGroup().equals("runelite") &&
event.getKey().equals("TooltipOverlay_preferredLocation") &&
!Strings.isNullOrEmpty(event.getNewValue()))
{
configManager.unsetConfiguration(event.getGroup(), event.getKey());
}
}
} }
@@ -5,6 +5,8 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.AccessLevel; import lombok.AccessLevel;
@@ -12,6 +14,8 @@ import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.client.RuneLite; import net.runelite.client.RuneLite;
import net.runelite.client.config.OpenOSRSConfig; import net.runelite.client.config.OpenOSRSConfig;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.events.ClientShutdown;
import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.ConfigChanged;
import net.runelite.client.ui.RuneLiteSplashScreen; import net.runelite.client.ui.RuneLiteSplashScreen;
import org.jgroups.Address; import org.jgroups.Address;
@@ -38,7 +42,7 @@ public class Groups extends ReceiverAdapter
private final PublishSubject<Message> messageObjectSubject = PublishSubject.create(); private final PublishSubject<Message> messageObjectSubject = PublishSubject.create();
@Inject @Inject
public Groups(OpenOSRSConfig openOSRSConfig) throws Exception public Groups(OpenOSRSConfig openOSRSConfig, EventBus eventBus) throws Exception
{ {
this.openOSRSConfig = openOSRSConfig; this.openOSRSConfig = openOSRSConfig;
@@ -47,6 +51,11 @@ public class Groups extends ReceiverAdapter
.setReceiver(this) .setReceiver(this)
.setDiscardOwnMessages(true) .setDiscardOwnMessages(true)
.connect("openosrs"); .connect("openosrs");
eventBus.subscribe(ClientShutdown.class, this, (e) -> {
Future<Void> f = close();
e.waitFor(f);
});
} }
public void broadcastSring(String command) public void broadcastSring(String command)
@@ -134,10 +143,22 @@ public class Groups extends ReceiverAdapter
{ {
messageObjectSubject.onNext(message); messageObjectSubject.onNext(message);
} }
} }
public void close() private CompletableFuture<Void> close()
{
CompletableFuture<Void> future = new CompletableFuture<>();
try
{ {
channel.close(); channel.close();
future.complete(null);
}
catch (Exception ex)
{
future.completeExceptionally(ex);
}
return future;
} }
} }
@@ -41,22 +41,18 @@ import java.awt.Toolkit;
import java.awt.TrayIcon; import java.awt.TrayIcon;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.concurrent.Callable;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.swing.ButtonModel;
import javax.swing.AbstractButton; import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
@@ -67,7 +63,6 @@ import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager; import javax.swing.ToolTipManager;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException; import javax.swing.UnsupportedLookAndFeelException;
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
import javax.swing.border.Border; import javax.swing.border.Border;
import javax.swing.border.CompoundBorder; import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
@@ -214,48 +209,6 @@ public class SwingUtil
return trayIcon; return trayIcon;
} }
/**
* Add graceful exit callback.
*
* @param frame the frame
* @param callback the callback
* @param confirmRequired the confirm required
*/
public static void addGracefulExitCallback(@Nonnull final JFrame frame, @Nonnull final Runnable callback, @Nonnull final Callable<Boolean> confirmRequired)
{
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent event)
{
int result = JOptionPane.OK_OPTION;
try
{
if (confirmRequired.call())
{
result = JOptionPane.showConfirmDialog(
frame,
"Are you sure you want to exit?", "Exit",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
}
}
catch (Exception e)
{
log.warn("Unexpected exception occurred while check for confirm required", e);
}
if (result == JOptionPane.OK_OPTION)
{
callback.run();
System.exit(0);
}
}
});
}
/** /**
* Create swing button from navigation button. * Create swing button from navigation button.
* *
@@ -83,7 +83,7 @@ public class WeaponMap
StyleMap.put(ItemID.BLACK_SWORD, WeaponStyle.MELEE); StyleMap.put(ItemID.BLACK_SWORD, WeaponStyle.MELEE);
StyleMap.put(ItemID.BLACK_WARHAMMER, WeaponStyle.MELEE); StyleMap.put(ItemID.BLACK_WARHAMMER, WeaponStyle.MELEE);
StyleMap.put(ItemID.BLADE_OF_SAELDOR, WeaponStyle.MELEE); StyleMap.put(ItemID.BLADE_OF_SAELDOR, WeaponStyle.MELEE);
StyleMap.put(ItemID.BLADE_OF_SAELDOR_I, WeaponStyle.MELEE); StyleMap.put(ItemID.BLADE_OF_SAELDOR_C, WeaponStyle.MELEE);
StyleMap.put(ItemID.BLADE_OF_SAELDOR_INACTIVE, WeaponStyle.MELEE); StyleMap.put(ItemID.BLADE_OF_SAELDOR_INACTIVE, WeaponStyle.MELEE);
StyleMap.put(ItemID.BLESSED_AXE, WeaponStyle.MELEE); StyleMap.put(ItemID.BLESSED_AXE, WeaponStyle.MELEE);
StyleMap.put(ItemID.BLUE_FLOWERS, WeaponStyle.MELEE); StyleMap.put(ItemID.BLUE_FLOWERS, WeaponStyle.MELEE);
@@ -8706,6 +8706,14 @@
20621, 20621,
20622 20622
], ],
"tangleroot": [
20661,
24555,
24557,
24559,
24561,
24563
],
"rift guardian": [ "rift guardian": [
20665, 20665,
20667, 20667,
@@ -1930,5 +1930,12 @@ public abstract class RSClientMixin implements RSClient
{ {
invertYaw = state; invertYaw = state;
} }
@Inject
@Override
public void stopNow()
{
setStopTimeMs(1);
}
} }
@@ -1245,4 +1245,7 @@ public interface RSClient extends RSGameShell, Client
@Import("showLoadingMessages") @Import("showLoadingMessages")
void setShowLoadingMessages(boolean showLoadingMessages); void setShowLoadingMessages(boolean showLoadingMessages);
@Import("stopTimeMs")
void setStopTimeMs(long time);
} }