diff --git a/runelite-api/src/main/java/net/runelite/api/ClanMember.java b/runelite-api/src/main/java/net/runelite/api/ClanMember.java new file mode 100644 index 0000000000..e32d0210a4 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/ClanMember.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api; + +public interface ClanMember +{ + String getUsername(); + + int getWorld(); + + ClanMemberRank getRank(); +} diff --git a/runelite-api/src/main/java/net/runelite/api/ClanMemberRank.java b/runelite-api/src/main/java/net/runelite/api/ClanMemberRank.java new file mode 100644 index 0000000000..a02e7ebf16 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/ClanMemberRank.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api; + +import java.util.HashMap; +import java.util.Map; + +public enum ClanMemberRank +{ + UNRANKED((byte) -1), + FRIEND((byte) 0), + RECRUIT((byte) 1), + CORPORAL((byte) 2), + SERGEANT((byte) 3), + LIEUTENANT((byte) 4), + CAPTAIN((byte) 5), + GENERAL((byte) 6), + OWNER((byte) 7); + + private static final Map BYTE_TO_RANK = new HashMap<>(); + + static + { + for (final ClanMemberRank clanMemberRank : ClanMemberRank.values()) + { + BYTE_TO_RANK.put(clanMemberRank.value, clanMemberRank); + } + } + + public static ClanMemberRank valueOf(byte rank) + { + return BYTE_TO_RANK.get(rank); + } + + private final byte value; + + ClanMemberRank(final byte value) + { + this.value = value; + } + + public byte getValue() + { + return value; + } +} 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 33718195eb..2461fa5507 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -130,6 +130,8 @@ public interface Client int getClanChatCount(); + ClanMember[] getClanMembers(); + HashTable getComponentTable(); boolean isPrayerActive(Prayer prayer); @@ -153,4 +155,10 @@ public interface Client IndexedSprite[] getMapScene(); SpritePixels[] getMapIcons(); + + IndexedSprite[] getModIcons(); + + void setModIcons(IndexedSprite[] modIcons); + + IndexedSprite createIndexedSprite(); } diff --git a/runelite-api/src/main/java/net/runelite/api/IndexedSprite.java b/runelite-api/src/main/java/net/runelite/api/IndexedSprite.java index 23394f194c..c60638d0fc 100644 --- a/runelite-api/src/main/java/net/runelite/api/IndexedSprite.java +++ b/runelite-api/src/main/java/net/runelite/api/IndexedSprite.java @@ -28,15 +28,33 @@ public interface IndexedSprite { byte[] getPixels(); + void setPixels(byte[] pixels); + int[] getPalette(); + void setPalette(int[] palette); + int getOffsetX(); + void setOffsetX(int offsetX); + int getOffsetY(); + void setOffsetY(int offsetY); + int getWidth(); + void setWidth(int width); + int getOriginalWidth(); + void setOriginalWidth(int originalWidth); + int getHeight(); + + void setHeight(int height); + + int getOriginalHeight(); + + void setOriginalHeight(int originalHeight); } diff --git a/runelite-api/src/main/java/net/runelite/api/MessageNode.java b/runelite-api/src/main/java/net/runelite/api/MessageNode.java index 0b9aa00835..9ec24b603b 100644 --- a/runelite-api/src/main/java/net/runelite/api/MessageNode.java +++ b/runelite-api/src/main/java/net/runelite/api/MessageNode.java @@ -28,8 +28,14 @@ public interface MessageNode { ChatMessageType getType(); + String getName(); + + void setName(String name); + String getSender(); + void setSender(String sender); + String getValue(); void setValue(String value); diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index f049e8a9c1..db7a1e2009 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -157,6 +157,12 @@ public class Hooks eventBus.post(varbitChanged); break; } + case "clanMembersChanged": + { + ClanMembersChanged clanMembersChanged = new ClanMembersChanged(); + eventBus.post(clanMembersChanged); + break; + } case "resizeChanged": { //maybe couple with varbitChanged. resizeable may not be a varbit but it would fit with the other client settings. diff --git a/runelite-client/src/main/java/net/runelite/client/events/ClanMembersChanged.java b/runelite-client/src/main/java/net/runelite/client/events/ClanMembersChanged.java new file mode 100644 index 0000000000..694c68e90d --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/events/ClanMembersChanged.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.events; + +import lombok.Data; + +@Data +public class ClanMembersChanged +{ +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java index d32c38f722..0fa1edfc45 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java @@ -45,9 +45,9 @@ import net.runelite.api.ItemComposition; import net.runelite.api.MessageNode; import net.runelite.api.Varbits; import net.runelite.client.config.ConfigManager; -import net.runelite.client.events.SetMessage; -import net.runelite.client.events.ResizeableChanged; import net.runelite.client.events.ConfigChanged; +import net.runelite.client.events.ResizeableChanged; +import net.runelite.client.events.SetMessage; import net.runelite.client.events.VarbitChanged; import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.Plugin; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatConfig.java new file mode 100644 index 0000000000..52b77240e4 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatConfig.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.clanchat; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup( + keyName = "clanchat", + name = "Clan Chat", + description = "Configuration for clan chat" +) +public interface ClanChatConfig extends Config +{ + @ConfigItem( + keyName = "clanRank", + name = "Show Clan Ranks Icon", + description = "Configures whether the clan ranks icons are shown next to name in chat" + ) + default boolean clanRank() + { + return true; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java index 12a1e9bdef..8b6574054b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/clanchat/ClanChatPlugin.java @@ -24,13 +24,37 @@ */ package net.runelite.client.plugins.clanchat; +import com.google.common.eventbus.Subscribe; +import com.google.inject.Provides; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBufferByte; +import java.awt.image.IndexColorModel; +import java.awt.image.WritableRaster; +import java.io.IOException; import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.Nullable; +import javax.imageio.ImageIO; import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.ChatMessageType; +import net.runelite.api.ClanMember; +import net.runelite.api.ClanMemberRank; import net.runelite.api.Client; import net.runelite.api.GameState; +import net.runelite.api.IndexedSprite; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.events.ClanMembersChanged; +import net.runelite.client.events.GameStateChanged; +import net.runelite.client.events.SetMessage; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.task.Schedule; @@ -38,12 +62,43 @@ import net.runelite.client.task.Schedule; @PluginDescriptor( name = "Clan chat plugin" ) +@Slf4j public class ClanChatPlugin extends Plugin { + private static final String[] CLANCHAT_IMAGES = + { + "Friend_clan_rank.png", "Recruit_clan_rank.png", + "Corporal_clan_rank.png", "Sergeant_clan_rank.png", + "Lieutenant_clan_rank.png", "Captain_clan_rank.png", + "General_clan_rank.png", "Owner_clan_rank.png" + }; + + private final Map clanRanksCache = new HashMap<>(); + private int modIconsLength; + @Inject @Nullable Client client; + @Inject + ClanChatConfig config; + + @Provides + ClanChatConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(ClanChatConfig.class); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged gameStateChanged) + { + if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN) + { + // this is after "Loading sprites" so we can modify modicons now + loadClanChatIcons(); + } + } + @Schedule( period = 600, unit = ChronoUnit.MILLIS @@ -61,4 +116,168 @@ public class ClanChatPlugin extends Plugin clanChatTitleWidget.setText("Clan Chat (" + client.getClanChatCount() + "/100)"); } } + + @Schedule( + period = 2, + unit = ChronoUnit.MINUTES + ) + public void cacheClanMemberRanks() + { + if (client.getGameState() != GameState.LOGGED_IN || !config.clanRank()) + { + return; + } + + clanRanksCache.clear(); + + final ClanMember[] clanMembersArr = client.getClanMembers(); + + if (clanMembersArr == null || clanMembersArr.length == 0) + { + return; + } + + final Set clanMembers = Arrays.stream(clanMembersArr) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + final int clanMembersSize = clanMembers.size(); + + if (clanMembersSize == 0) + { + return; + } + + log.debug("Caching clan members..."); + + for (ClanMember clanMember : clanMembers) + { + final String name = sanitize(clanMember.getUsername()); + final ClanMemberRank rank = clanMember.getRank(); + + if (rank != null) + { + clanRanksCache.put(name, rank); + } + } + } + + @Subscribe + public void onClanMembersChanged(ClanMembersChanged event) + { + cacheClanMemberRanks(); + } + + @Subscribe + public void onSetMessage(SetMessage setMessage) + { + if (client.getGameState() != GameState.LOGGED_IN) + { + return; + } + + if (config.clanRank() && setMessage.getType() == ChatMessageType.CLANCHAT) + { + insertClanRankIcon(setMessage); + } + } + + private void loadClanChatIcons() + { + try + { + final IndexedSprite[] modIcons = client.getModIcons(); + final IndexedSprite[] newModIcons = Arrays.copyOf(modIcons, modIcons.length + CLANCHAT_IMAGES.length); + int curPosition = newModIcons.length - CLANCHAT_IMAGES.length; + + for (String resource : CLANCHAT_IMAGES) + { + IndexedSprite sprite = createIndexedSprite(resource); + newModIcons[curPosition++] = sprite; + } + + client.setModIcons(newModIcons); + modIconsLength = newModIcons.length; + } + catch (IOException e) + { + log.warn("Failed loading of clan chat icons", e); + modIconsLength = 0; + } + } + + private IndexedSprite createIndexedSprite(final String imagePath) throws IOException + { + final BufferedImage bufferedImage = rgbaToIndexedBufferedImage(ImageIO + .read(this.getClass().getResource(imagePath))); + + final IndexColorModel indexedCM = (IndexColorModel) bufferedImage.getColorModel(); + + final int width = bufferedImage.getWidth(); + final int height = bufferedImage.getHeight(); + final byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData(); + final int[] palette = new int[indexedCM.getMapSize()]; + indexedCM.getRGBs(palette); + + final IndexedSprite newIndexedSprite = client.createIndexedSprite(); + newIndexedSprite.setPixels(pixels); + newIndexedSprite.setPalette(palette); + newIndexedSprite.setWidth(width); + newIndexedSprite.setHeight(height); + newIndexedSprite.setOriginalWidth(width); + newIndexedSprite.setOriginalHeight(height); + newIndexedSprite.setOffsetX(0); + newIndexedSprite.setOffsetY(0); + return newIndexedSprite; + } + + private static BufferedImage rgbaToIndexedBufferedImage(final BufferedImage sourceBufferedImage) + { + final BufferedImage indexedImage = new BufferedImage( + sourceBufferedImage.getWidth(), + sourceBufferedImage.getHeight(), + BufferedImage.TYPE_BYTE_INDEXED); + + final ColorModel cm = indexedImage.getColorModel(); + final IndexColorModel icm = (IndexColorModel) cm; + + final int size = icm.getMapSize(); + final byte[] reds = new byte[size]; + final byte[] greens = new byte[size]; + final byte[] blues = new byte[size]; + icm.getReds(reds); + icm.getGreens(greens); + icm.getBlues(blues); + + final WritableRaster raster = indexedImage.getRaster(); + final int pixel = raster.getSample(0, 0, 0); + final IndexColorModel resultIcm = new IndexColorModel(8, size, reds, greens, blues, pixel); + final BufferedImage resultIndexedImage = new BufferedImage(resultIcm, raster, sourceBufferedImage.isAlphaPremultiplied(), null); + resultIndexedImage.getGraphics().drawImage(sourceBufferedImage, 0, 0, null); + return resultIndexedImage; + } + + private void insertClanRankIcon(final SetMessage message) + { + final String playerName = sanitize(message.getName()); + final ClanMemberRank rank = clanRanksCache.get(playerName); + + if (rank != null && rank != ClanMemberRank.UNRANKED) + { + int iconNumber = getIconNumber(rank); + message.getMessageNode() + .setSender(message.getMessageNode().getSender() + " "); + client.refreshChat(); + } + } + + private int getIconNumber(final ClanMemberRank clanMemberRank) + { + return modIconsLength - CLANCHAT_IMAGES.length + clanMemberRank.getValue(); + } + + private static String sanitize(String lookup) + { + final String cleaned = lookup.contains("') + 1) : lookup; + return cleaned.replace('\u00A0', ' '); + } } diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Captain_clan_rank.png b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Captain_clan_rank.png new file mode 100644 index 0000000000..82c206703c Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Captain_clan_rank.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Corporal_clan_rank.png b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Corporal_clan_rank.png new file mode 100644 index 0000000000..b9e8513f56 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Corporal_clan_rank.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Friend_clan_rank.png b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Friend_clan_rank.png new file mode 100644 index 0000000000..ab752bdaaf Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Friend_clan_rank.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/General_clan_rank.png b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/General_clan_rank.png new file mode 100644 index 0000000000..ebc6e9847b Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/General_clan_rank.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Lieutenant_clan_rank.png b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Lieutenant_clan_rank.png new file mode 100644 index 0000000000..d6a18d5f8d Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Lieutenant_clan_rank.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Owner_clan_rank.png b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Owner_clan_rank.png new file mode 100644 index 0000000000..1e982ad7c1 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Owner_clan_rank.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Recruit_clan_rank.png b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Recruit_clan_rank.png new file mode 100644 index 0000000000..01a7aa4256 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Recruit_clan_rank.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Sergeant_clan_rank.png b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Sergeant_clan_rank.png new file mode 100644 index 0000000000..a12a7a5e75 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/clanchat/Sergeant_clan_rank.png differ diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClanMemberMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClanMemberMixin.java new file mode 100644 index 0000000000..d21dc7aba1 --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClanMemberMixin.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016-2017, Adam + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.mixins; + +import net.runelite.api.ClanMemberRank; +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.Mixin; +import net.runelite.rs.api.RSClanMember; + +@Mixin(RSClanMember.class) +public abstract class RSClanMemberMixin implements RSClanMember +{ + @Override + @Inject + public ClanMemberRank getRank() + { + return ClanMemberRank.valueOf(getRSRank()); + } +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index e62763c8cc..b19752522c 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -27,6 +27,7 @@ package net.runelite.mixins; import java.util.ArrayList; import java.util.List; import net.runelite.api.GameState; +import net.runelite.api.IndexedSprite; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; import net.runelite.api.NPC; @@ -35,11 +36,12 @@ import net.runelite.api.Point; import net.runelite.api.Prayer; import net.runelite.api.Skill; import net.runelite.api.Varbits; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; import net.runelite.api.mixins.Inject; import net.runelite.api.mixins.Mixin; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; import net.runelite.rs.api.RSClient; +import net.runelite.rs.api.RSIndexedSprite; import net.runelite.rs.api.RSWidget; @Mixin(RSClient.class) @@ -314,4 +316,11 @@ public abstract class RSClientMixin implements RSClient setMenuOptionCount(count); } + + @Inject + @Override + public void setModIcons(IndexedSprite[] modIcons) + { + setRSModIcons((RSIndexedSprite[]) modIcons); + } } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClanMember.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClanMember.java index fa7bd19f1e..aad35a71d5 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClanMember.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClanMember.java @@ -24,16 +24,17 @@ */ package net.runelite.rs.api; +import net.runelite.api.ClanMember; import net.runelite.mapping.Import; -public interface RSClanMember +public interface RSClanMember extends ClanMember { @Import("username") - String getUsernameName(); + String getUsername(); @Import("world") int getWorld(); @Import("rank") - byte getRank(); + byte getRSRank(); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index 6a437ad0be..b1c72a5ed5 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -26,6 +26,7 @@ package net.runelite.rs.api; import java.util.Map; import net.runelite.api.Client; +import net.runelite.mapping.Construct; import net.runelite.mapping.Import; public interface RSClient extends RSGameEngine, Client @@ -320,4 +321,15 @@ public interface RSClient extends RSGameEngine, Client @Import("mapIcons") @Override RSSpritePixels[] getMapIcons(); + + @Import("modIcons") + @Override + RSIndexedSprite[] getModIcons(); + + @Import("modIcons") + void setRSModIcons(RSIndexedSprite[] modIcons); + + @Construct + @Override + RSIndexedSprite createIndexedSprite(); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSIndexedSprite.java b/runescape-api/src/main/java/net/runelite/rs/api/RSIndexedSprite.java index b18a753fdf..01988e04cc 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSIndexedSprite.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSIndexedSprite.java @@ -33,27 +33,63 @@ public interface RSIndexedSprite extends IndexedSprite @Override byte[] getPixels(); + @Import("pixels") + @Override + void setPixels(byte[] pixels); + @Import("palette") @Override int[] getPalette(); + @Import("palette") + @Override + void setPalette(int[] palette); + @Import("originalWidth") @Override int getOriginalWidth(); + @Import("originalWidth") + @Override + void setOriginalWidth(int originalWidth); + + @Import("originalHeight") + @Override + int getOriginalHeight(); + + @Import("originalHeight") + @Override + void setOriginalHeight(int originalHeight); + @Import("height") @Override int getHeight(); + @Import("height") + @Override + void setHeight(int height); + @Import("offsetX") @Override int getOffsetX(); + @Import("offsetX") + @Override + void setOffsetX(int offsetX); + @Import("offsetY") @Override int getOffsetY(); + @Import("offsetY") + @Override + void setOffsetY(int offsetY); + @Import("width") @Override int getWidth(); + + @Import("width") + @Override + void setWidth(int width); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSMessageNode.java b/runescape-api/src/main/java/net/runelite/rs/api/RSMessageNode.java index acffadcb6a..be3d845a48 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSMessageNode.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSMessageNode.java @@ -32,10 +32,22 @@ public interface RSMessageNode extends MessageNode @Import("type") int getRSType(); + @Import("name") + @Override + String getName(); + + @Import("name") + @Override + void setName(String name); + @Import("sender") @Override String getSender(); + @Import("sender") + @Override + void setSender(String sender); + @Import("value") @Override String getValue();