From 68d448b7de35f5287fd3061fb418db87a3d2486d Mon Sep 17 00:00:00 2001 From: UniquePassive Date: Thu, 11 Jan 2018 00:03:16 +0100 Subject: [PATCH] Implement optimized isFriend, isIgnore and isClanMember --- .../main/java/net/runelite/api/Client.java | 6 + .../mixins/PlayerIsClanMemberMixin.java | 96 ++++++++++++++++ .../runelite/mixins/PlayerIsFriendMixin.java | 105 ++++++++++++++++++ .../runelite/mixins/PlayerIsIgnoredMixin.java | 94 ++++++++++++++++ .../net/runelite/mixins/RSFriendMixin.java | 63 +++++++++++ 5 files changed, 364 insertions(+) create mode 100644 runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsClanMemberMixin.java create mode 100644 runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsFriendMixin.java create mode 100644 runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsIgnoredMixin.java create mode 100644 runelite-mixins/src/main/java/net/runelite/mixins/RSFriendMixin.java diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index b59ab26d79..d33eeaa34c 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -161,4 +161,10 @@ public interface Client void setModIcons(IndexedSprite[] modIcons); IndexedSprite createIndexedSprite(); + + boolean isFriend(String name, boolean mustBeLoggedIn); + + boolean isIgnored(String name); + + boolean isClanMember(String name); } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsClanMemberMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsClanMemberMixin.java new file mode 100644 index 0000000000..6bada45152 --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsClanMemberMixin.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018, UniquePassive + * 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.mixins; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import java.util.concurrent.TimeUnit; +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.Mixin; +import net.runelite.api.mixins.Shadow; +import net.runelite.rs.api.RSClanMember; +import net.runelite.rs.api.RSClient; + +@Mixin(RSClient.class) +public abstract class PlayerIsClanMemberMixin implements RSClient +{ + @Shadow("clanChatCount") + private static int clanChatCount; + + @Inject + private static int oldClanChatCount; + + @Inject + private static Cache cachedClanMembers; + + @Inject + @Override + public boolean isClanMember(String name) + { + if (name == null) + { + return false; + } + + if (cachedClanMembers == null) + { + cachedClanMembers = CacheBuilder + .newBuilder() + .expireAfterAccess(1, TimeUnit.MINUTES) + .build(); + } + + if (oldClanChatCount != clanChatCount) + { + cachedClanMembers.invalidateAll(); + oldClanChatCount = clanChatCount; + } + + Boolean isClanMember = cachedClanMembers.getIfPresent(name); + + if (isClanMember == null) + { + isClanMember = false; + + for (RSClanMember clanMember : getClanMembers()) + { + if (clanMember == null) + { + continue; + } + + if (name.equals(clanMember.getUsername())) + { + isClanMember = true; + break; + } + } + + cachedClanMembers.put(name, isClanMember); + } + + return isClanMember; + } +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsFriendMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsFriendMixin.java new file mode 100644 index 0000000000..2565cc2166 --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsFriendMixin.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2018, UniquePassive + * 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.mixins; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import java.util.concurrent.TimeUnit; +import net.runelite.api.mixins.Copy; +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.Mixin; +import net.runelite.api.mixins.Replace; +import net.runelite.api.mixins.Shadow; +import net.runelite.rs.api.RSClient; + +@Mixin(RSClient.class) +public abstract class PlayerIsFriendMixin implements RSClient +{ + @Shadow("friendCount") + private static int friendCount; + + @Inject + private static int oldFriendCount; + + @Inject + private static Cache cachedFriends; + + @Inject + private static Cache cachedOnlineFriends; + + @Copy("isFriended") + private static boolean rs$isFriended(String name, boolean mustBeLoggedIn) + { + throw new IllegalStateException(); + } + + @Replace("isFriended") + private static boolean rl$isFriended(String name, boolean mustBeLoggedIn) + { + if (name == null) + { + return false; + } + + if (cachedFriends == null) + { + cachedFriends = CacheBuilder + .newBuilder() + .expireAfterAccess(1, TimeUnit.MINUTES) + .build(); + + cachedOnlineFriends = CacheBuilder + .newBuilder() + .expireAfterAccess(1, TimeUnit.MINUTES) + .build(); + } + + if (oldFriendCount != friendCount) + { + cachedFriends.invalidateAll(); + cachedOnlineFriends.invalidateAll(); + + oldFriendCount = friendCount; + } + + Cache cache = mustBeLoggedIn ? cachedOnlineFriends : cachedFriends; + Boolean isFriended = cache.getIfPresent(name); + + if (isFriended == null) + { + isFriended = rs$isFriended(name, mustBeLoggedIn); + cache.put(name, isFriended); + } + + return isFriended; + } + + @Inject + @Override + public boolean isFriend(String name, boolean mustBeLoggedIn) + { + return rl$isFriended(name, mustBeLoggedIn); + } +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsIgnoredMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsIgnoredMixin.java new file mode 100644 index 0000000000..cdf784983d --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/PlayerIsIgnoredMixin.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018, UniquePassive + * 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.mixins; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import java.util.concurrent.TimeUnit; +import net.runelite.api.mixins.Copy; +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.Mixin; +import net.runelite.api.mixins.Replace; +import net.runelite.api.mixins.Shadow; +import net.runelite.rs.api.RSClient; + +@Mixin(RSClient.class) +public abstract class PlayerIsIgnoredMixin implements RSClient +{ + @Shadow("ignoreCount") + private static int ignoreCount; + + @Inject + private static int oldIgnoreCount; + + @Inject + private static Cache cachedIgnored; + + @Copy("isIgnored") + private static boolean rs$isIgnored(String name) + { + throw new IllegalStateException(); + } + + @Replace("isIgnored") + private static boolean rl$isIgnored(String name) + { + if (name == null) + { + return false; + } + + if (cachedIgnored == null) + { + cachedIgnored = CacheBuilder + .newBuilder() + .expireAfterAccess(1, TimeUnit.MINUTES) + .build(); + } + + if (oldIgnoreCount != ignoreCount) + { + cachedIgnored.invalidateAll(); + oldIgnoreCount = ignoreCount; + } + + Boolean isIgnored = cachedIgnored.getIfPresent(name); + + if (isIgnored == null) + { + isIgnored = rs$isIgnored(name); + cachedIgnored.put(name, isIgnored); + } + + return isIgnored; + } + + @Inject + @Override + public boolean isIgnored(String name) + { + return rl$isIgnored(name); + } +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSFriendMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSFriendMixin.java new file mode 100644 index 0000000000..40d70d7ad2 --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSFriendMixin.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, UniquePassive + * 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.mixins; + +import com.google.common.cache.Cache; +import net.runelite.api.mixins.FieldHook; +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.Mixin; +import net.runelite.api.mixins.Shadow; +import net.runelite.rs.api.RSFriend; + +@Mixin(RSFriend.class) +public abstract class RSFriendMixin implements RSFriend +{ + @Shadow("cachedFriends") + private static Cache cachedFriends; + + @Shadow("cachedOnlineFriends") + private static Cache cachedOnlineFriends; + + @FieldHook("previousName") + @Inject + public void previousNameChanged(int idx) + { + if (cachedFriends != null) + { + cachedFriends.invalidate(getPreviousName()); + cachedOnlineFriends.invalidate(getPreviousName()); + } + } + + @FieldHook("world") + @Inject + public void worldChanged(int idx) + { + if (cachedFriends != null) + { + cachedOnlineFriends.invalidate(getName()); + } + } +}