diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 9fcc75dffa..5580c3b6e4 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -25,9 +25,9 @@ object ProjectVersions { const val launcherVersion = "2.0.4" - const val rlVersion = "1.6.3-SNAPSHOT" + const val rlVersion = "1.6.4" - const val openosrsVersion = "2.1.22-SNAPSHOT" + const val openosrsVersion = "2.1.23" const val rsversion = 187 const val cacheversion = 165 diff --git a/cache/src/main/java/net/runelite/cache/ConfigType.java b/cache/src/main/java/net/runelite/cache/ConfigType.java index 13056e2e33..4ca51a0b33 100644 --- a/cache/src/main/java/net/runelite/cache/ConfigType.java +++ b/cache/src/main/java/net/runelite/cache/ConfigType.java @@ -43,6 +43,7 @@ public enum ConfigType VARCLIENT(19), VARCLIENTSTRING(15), VARPLAYER(16), + HITSPLAT(32), STRUCT(34), AREA(35); diff --git a/cache/src/main/java/net/runelite/cache/definitions/HitSplatDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/HitSplatDefinition.java new file mode 100644 index 0000000000..2f9a0d1359 --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/HitSplatDefinition.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020, Hexagon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions; + +import lombok.Data; + +@Data +public class HitSplatDefinition +{ + private String stringFormat = ""; + private int varbitID = -1; + private int leftSprite = -1; + private int leftSprite2 = -1; + private int rightSpriteId = -1; + private int fontType = -1; + private int backgroundSprite = -1; + private int varpID = -1; + private int useDamage = -1; + private int textColor = 0xFFFFFF; + private int displayCycles = 70; + private int[] multihitsplats; + private int scrollToOffsetX = 0; + private int fadeStartCycle = -1; + private int scrollToOffsetY = 0; + private int textOffsetY = 0; +} diff --git a/cache/src/main/java/net/runelite/cache/definitions/InterfaceDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/InterfaceDefinition.java index aede6d6d7b..4ba97725d4 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/InterfaceDefinition.java +++ b/cache/src/main/java/net/runelite/cache/definitions/InterfaceDefinition.java @@ -46,7 +46,7 @@ public class InterfaceDefinition public int scrollWidth; public int scrollHeight; public boolean noClickThrough; - public int spriteId; + public int spriteId = -1; public int textureId; public boolean spriteTiling; public int opacity; @@ -54,34 +54,34 @@ public class InterfaceDefinition public int shadowColor; public boolean flippedVertically; public boolean flippedHorizontally; - public int modelType; - public int modelId; + public int modelType = 1; + public int modelId = -1; public int offsetX2d; public int offsetY2d; public int rotationX; public int rotationY; public int rotationZ; - public int modelZoom; - public int animation; + public int modelZoom = 100; + public int animation = -1; public boolean orthogonal; public int modelHeightOverride; - public int fontId; - public String text; + public int fontId = -1; + public String text = ""; public int lineHeight; public int xTextAlignment; public int yTextAlignment; public boolean textShadowed; public int textColor; public boolean filled; - public int lineWidth; + public int lineWidth = 1; public boolean lineDirection; public int clickMask; - public String name; + public String name = ""; public String[] actions; public int dragDeadZone; public int dragDeadTime; public boolean dragRenderBehavior; - public String targetVerb; + public String targetVerb = ""; public Object[] onLoadListener; public Object[] onMouseOverListener; public Object[] onMouseLeaveListener; @@ -119,13 +119,13 @@ public class InterfaceDefinition public int[] yOffsets; public int[] sprites; public String[] configActions; - public String alternateText; + public String alternateText = ""; public int alternateTextColor; public int hoveredTextColor; public int alternateHoveredTextColor; - public int alternateSpriteId; - public int alternateModelId; - public int alternateAnimation; - public String spellName; - public String tooltip; + public int alternateSpriteId = -1; + public int alternateModelId = -1; + public int alternateAnimation = -1; + public String spellName = ""; + public String tooltip = "Ok"; } diff --git a/cache/src/main/java/net/runelite/cache/definitions/WorldMapDefinition.java b/cache/src/main/java/net/runelite/cache/definitions/WorldMapDefinition.java index a8333263e5..30c61f73b4 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/WorldMapDefinition.java +++ b/cache/src/main/java/net/runelite/cache/definitions/WorldMapDefinition.java @@ -33,13 +33,13 @@ public class WorldMapDefinition { public String name; public int field450; - public int field451; + public int defaultZoom; public int fileId; public int field453; public int field454; public int field456; - public boolean field457; - public List field458; + public boolean isSurface; + public List regionList; public String safeName; public Position position; public int field463; diff --git a/cache/src/main/java/net/runelite/cache/definitions/WorldMapType0.java b/cache/src/main/java/net/runelite/cache/definitions/WorldMapType0.java index 1294d0eb4d..cecc41f524 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/WorldMapType0.java +++ b/cache/src/main/java/net/runelite/cache/definitions/WorldMapType0.java @@ -29,14 +29,14 @@ @Data public class WorldMapType0 implements WorldMapTypeBase { - public int field600; - public int field601; - public int field602; - public int field603; - public int field604; - public int field605; - public int field606; - public int field607; - public int field608; - public int field609; + public int chunk_xHigh; + public int xLow; + public int chunk_xLow; + public int yLow; + public int xHigh; + public int numberOfPlanes; + public int plane; + public int chunk_yLow; + public int yHigh; + public int chunk_yHigh; } diff --git a/cache/src/main/java/net/runelite/cache/definitions/WorldMapType1.java b/cache/src/main/java/net/runelite/cache/definitions/WorldMapType1.java index 15a4f3e28d..4d4cd50d21 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/WorldMapType1.java +++ b/cache/src/main/java/net/runelite/cache/definitions/WorldMapType1.java @@ -29,14 +29,14 @@ @Data public class WorldMapType1 implements WorldMapTypeBase { - public int field424; - public int field425; - public int field426; - public int field427; - public int field428; - public int field429; - public int field431; - public int field433; - public int field434; - public int field435; + public int numberOfPlanes; + public int xLowerLeft; + public int yLowerLeft; + public int xLowerRight; + public int yLowerRight; + public int xUpperLeft; + public int yUpperLeft; + public int xUpperRight; + public int plane; + public int yUpperRight; } diff --git a/cache/src/main/java/net/runelite/cache/definitions/WorldMapType2.java b/cache/src/main/java/net/runelite/cache/definitions/WorldMapType2.java index 7b5326814d..3670f99dd0 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/WorldMapType2.java +++ b/cache/src/main/java/net/runelite/cache/definitions/WorldMapType2.java @@ -29,10 +29,10 @@ @Data public class WorldMapType2 implements WorldMapTypeBase { - public int field510; - public int field511; - public int field512; - public int field514; - public int field515; - public int field519; + public int xLow; + public int numberOfPlanes; + public int yLow; + public int xHigh; + public int yHigh; + public int plane; } diff --git a/cache/src/main/java/net/runelite/cache/definitions/WorldMapType3.java b/cache/src/main/java/net/runelite/cache/definitions/WorldMapType3.java index 433c8a17fa..10d55418e0 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/WorldMapType3.java +++ b/cache/src/main/java/net/runelite/cache/definitions/WorldMapType3.java @@ -29,18 +29,18 @@ @Data public class WorldMapType3 implements WorldMapTypeBase { - public int field376; - public int field377; - public int field378; - public int field379; - public int field380; - public int field381; - public int field382; - public int field383; - public int field384; - public int field385; - public int field386; - public int field387; - public int field388; - public int field389; + public int chunk_oldXHigh; + public int numberOfPlanes; + public int oldX; + public int chunk_oldYHigh; + public int newX; + public int newY; + public int chunk_oldXLow; + public int oldY; + public int chunk_newYLow; + public int chunk_oldYLow; + public int chunk_newXLow; + public int oldPlane; + public int chunk_newXHigh; + public int chunk_newYHigh; } diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/HitSplatLoader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/HitSplatLoader.java new file mode 100644 index 0000000000..adf8c37ffc --- /dev/null +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/HitSplatLoader.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2020, Hexagon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache.definitions.loaders; + +import net.runelite.cache.definitions.HitSplatDefinition; +import net.runelite.cache.io.InputStream; + +public class HitSplatLoader +{ + public HitSplatDefinition load(byte[] data) + { + HitSplatDefinition def = new HitSplatDefinition(); + InputStream stream = new InputStream(data); + + for (; ; ) + { + int opcode = stream.readUnsignedByte(); + + switch (opcode) + { + case 0: + return def; + case 1: + def.setFontType(stream.readBigSmart2()); + break; + case 2: + def.setTextColor(stream.read24BitInt()); + break; + case 3: + def.setLeftSprite(stream.readBigSmart2()); + break; + case 4: + def.setLeftSprite2(stream.readBigSmart2()); + break; + case 5: + def.setBackgroundSprite(stream.readBigSmart2()); + break; + case 6: + def.setRightSpriteId(stream.readBigSmart2()); + break; + case 7: + def.setScrollToOffsetX(stream.readShort()); + break; + case 8: + def.setStringFormat(stream.readString2()); + break; + case 9: + def.setDisplayCycles(stream.readUnsignedShort()); + break; + case 10: + def.setScrollToOffsetY(stream.readShort()); + break; + case 11: + def.setFadeStartCycle(0); + break; + case 12: + def.setUseDamage(stream.readUnsignedByte()); + break; + case 13: + def.setTextOffsetY(stream.readShort()); + break; + case 14: + def.setFadeStartCycle(stream.readUnsignedShort()); + break; + case 17: + case 18: + int varbitId = stream.readUnsignedShort(); + + if (varbitId == 0xFFFF) + { + varbitId = -1; + } + def.setVarbitID(varbitId); + + int varp = stream.readUnsignedShort(); + if (varp == 0xFFFF) + { + varp = -1; + } + def.setVarpID(varp); + + int id = -1; + if (opcode == 18) + { + id = stream.readUnsignedShort(); + if (id == 0xFFFF) + { + id = -1; + } + } + + int length = stream.readUnsignedByte(); + int[] multihitsplats = new int[length + 2]; + + for (int i = 0; i <= length; i++) + { + multihitsplats[i] = stream.readUnsignedShort(); + if (multihitsplats[i] == 0xFFFF) + { + multihitsplats[i] = -1; + } + } + + multihitsplats[length + 1] = id; + + def.setMultihitsplats(multihitsplats); + break; + } + } + } +} diff --git a/cache/src/main/java/net/runelite/cache/definitions/loaders/WorldMapLoader.java b/cache/src/main/java/net/runelite/cache/definitions/loaders/WorldMapLoader.java index 3ce0bf4c3d..371b6491c1 100644 --- a/cache/src/main/java/net/runelite/cache/definitions/loaders/WorldMapLoader.java +++ b/cache/src/main/java/net/runelite/cache/definitions/loaders/WorldMapLoader.java @@ -61,14 +61,14 @@ public WorldMapDefinition load(byte[] b, int fileId) def.field450 = in.readInt(); in.readUnsignedByte(); - def.field457 = in.readUnsignedByte() == 1; - def.field451 = in.readUnsignedByte(); + def.isSurface = in.readUnsignedByte() == 1; + def.defaultZoom = in.readUnsignedByte(); int var3 = in.readUnsignedByte(); - def.field458 = new LinkedList(); + def.regionList = new LinkedList(); for (int var4 = 0; var4 < var3; ++var4) { - def.field458.add(this.loadType(in)); + def.regionList.add(this.loadType(in)); } return def; @@ -110,16 +110,16 @@ private WorldMapTypeBase load0(InputStream in) { WorldMapType0 wm = new WorldMapType0(); - wm.field606 = in.readUnsignedByte(); - wm.field605 = in.readUnsignedByte(); - wm.field601 = in.readUnsignedShort(); - wm.field602 = in.readUnsignedByte(); - wm.field603 = in.readUnsignedShort(); - wm.field607 = in.readUnsignedByte(); - wm.field604 = in.readUnsignedShort(); - wm.field600 = in.readUnsignedByte(); - wm.field608 = in.readUnsignedShort(); - wm.field609 = in.readUnsignedByte(); + wm.plane = in.readUnsignedByte(); + wm.numberOfPlanes = in.readUnsignedByte(); + wm.xLow = in.readUnsignedShort(); + wm.chunk_xLow = in.readUnsignedByte(); + wm.yLow = in.readUnsignedShort(); + wm.chunk_yLow = in.readUnsignedByte(); + wm.xHigh = in.readUnsignedShort(); + wm.chunk_xHigh = in.readUnsignedByte(); + wm.yHigh = in.readUnsignedShort(); + wm.chunk_yHigh = in.readUnsignedByte(); return wm; } @@ -128,16 +128,16 @@ private WorldMapTypeBase load1(InputStream in) { WorldMapType1 wm = new WorldMapType1(); - wm.field434 = in.readUnsignedByte(); - wm.field424 = in.readUnsignedByte(); - wm.field425 = in.readUnsignedShort(); - wm.field426 = in.readUnsignedShort(); - wm.field427 = in.readUnsignedShort(); - wm.field431 = in.readUnsignedShort(); - wm.field429 = in.readUnsignedShort(); - wm.field428 = in.readUnsignedShort(); - wm.field433 = in.readUnsignedShort(); - wm.field435 = in.readUnsignedShort(); + wm.plane = in.readUnsignedByte(); + wm.numberOfPlanes = in.readUnsignedByte(); + wm.xLowerLeft = in.readUnsignedShort(); + wm.yLowerLeft = in.readUnsignedShort(); + wm.xLowerRight = in.readUnsignedShort(); + wm.yUpperLeft = in.readUnsignedShort(); + wm.xUpperLeft = in.readUnsignedShort(); + wm.yLowerRight = in.readUnsignedShort(); + wm.xUpperRight = in.readUnsignedShort(); + wm.yUpperRight = in.readUnsignedShort(); return wm; } @@ -146,12 +146,12 @@ private WorldMapTypeBase load2(InputStream in) { WorldMapType2 wm = new WorldMapType2(); - wm.field519 = in.readUnsignedByte(); - wm.field511 = in.readUnsignedByte(); - wm.field510 = in.readUnsignedShort(); - wm.field512 = in.readUnsignedShort(); - wm.field514 = in.readUnsignedShort(); - wm.field515 = in.readUnsignedShort(); + wm.plane = in.readUnsignedByte(); + wm.numberOfPlanes = in.readUnsignedByte(); + wm.xLow = in.readUnsignedShort(); + wm.yLow = in.readUnsignedShort(); + wm.xHigh = in.readUnsignedShort(); + wm.yHigh = in.readUnsignedShort(); return wm; } @@ -160,20 +160,20 @@ private WorldMapTypeBase load3(InputStream in) { WorldMapType3 wm = new WorldMapType3(); - wm.field387 = in.readUnsignedByte(); - wm.field377 = in.readUnsignedByte(); - wm.field378 = in.readUnsignedShort(); - wm.field382 = in.readUnsignedByte(); - wm.field376 = in.readUnsignedByte(); - wm.field383 = in.readUnsignedShort(); - wm.field385 = in.readUnsignedByte(); - wm.field379 = in.readUnsignedByte(); - wm.field380 = in.readUnsignedShort(); - wm.field386 = in.readUnsignedByte(); - wm.field388 = in.readUnsignedByte(); - wm.field381 = in.readUnsignedShort(); - wm.field384 = in.readUnsignedByte(); - wm.field389 = in.readUnsignedByte(); + wm.oldPlane = in.readUnsignedByte(); + wm.numberOfPlanes = in.readUnsignedByte(); + wm.oldX = in.readUnsignedShort(); + wm.chunk_oldXLow = in.readUnsignedByte(); + wm.chunk_oldXHigh = in.readUnsignedByte(); + wm.oldY = in.readUnsignedShort(); + wm.chunk_oldYLow = in.readUnsignedByte(); + wm.chunk_oldYHigh = in.readUnsignedByte(); + wm.newX = in.readUnsignedShort(); + wm.chunk_newXLow = in.readUnsignedByte(); + wm.chunk_newXHigh = in.readUnsignedByte(); + wm.newY = in.readUnsignedShort(); + wm.chunk_newYLow = in.readUnsignedByte(); + wm.chunk_newYHigh = in.readUnsignedByte(); return wm; } diff --git a/cache/src/main/java/net/runelite/cache/io/InputStream.java b/cache/src/main/java/net/runelite/cache/io/InputStream.java index 1fde0d97a3..33c2cd484c 100644 --- a/cache/src/main/java/net/runelite/cache/io/InputStream.java +++ b/cache/src/main/java/net/runelite/cache/io/InputStream.java @@ -200,6 +200,18 @@ public String readString() return sb.toString(); } + public String readString2() + { + if (this.readByte() != 0) + { + throw new IllegalStateException("Invalid jstr2"); + } + else + { + return readString(); + } + } + public String readStringOrNull() { if (this.peek() != 0) diff --git a/cache/src/test/java/net/runelite/cache/HitSplatDumper.java b/cache/src/test/java/net/runelite/cache/HitSplatDumper.java new file mode 100644 index 0000000000..09d3fa2b61 --- /dev/null +++ b/cache/src/test/java/net/runelite/cache/HitSplatDumper.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020, Hexagon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.cache; + +import com.google.common.io.Files; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import lombok.extern.slf4j.Slf4j; +import net.runelite.cache.definitions.HitSplatDefinition; +import net.runelite.cache.definitions.loaders.HitSplatLoader; +import net.runelite.cache.fs.Archive; +import net.runelite.cache.fs.ArchiveFiles; +import net.runelite.cache.fs.FSFile; +import net.runelite.cache.fs.Index; +import net.runelite.cache.fs.Storage; +import net.runelite.cache.fs.Store; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +@Slf4j +public class HitSplatDumper +{ + private Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + @Rule + public TemporaryFolder folder = StoreLocation.getTemporaryFolder(); + + @Test + @Ignore + public void test() throws IOException + { + File dumpDir = folder.newFolder(); + int count = 0; + + try (Store store = new Store(StoreLocation.LOCATION)) + { + store.load(); + + Storage storage = store.getStorage(); + Index index = store.getIndex(IndexType.CONFIGS); + Archive archive = index.getArchive(ConfigType.HITSPLAT.getId()); + + HitSplatLoader loader = new HitSplatLoader(); + + byte[] archiveData = storage.loadArchive(archive); + ArchiveFiles files = archive.getFiles(archiveData); + + for (FSFile file : files.getFiles()) + { + byte[] b = file.getContents(); + + HitSplatDefinition def = loader.load(b); + + Files.asCharSink(new File(dumpDir, file.getFileId() + ".json"), Charset.defaultCharset()).write(gson.toJson(def)); + ++count; + } + } + + log.info("Dumped {} hitsplats to {}", count, dumpDir); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSprite.java b/http-api/src/main/java/net/runelite/http/api/npc/NpcInfo.java similarity index 68% rename from runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSprite.java rename to http-api/src/main/java/net/runelite/http/api/npc/NpcInfo.java index b470dc2212..285169a32d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiSprite.java +++ b/http-api/src/main/java/net/runelite/http/api/npc/NpcInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Abex + * Copyright (c) 2020, Adam * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,24 +22,14 @@ * (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.wiki; +package net.runelite.http.api.npc; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import net.runelite.api.SpriteID; -import net.runelite.client.game.SpriteOverride; +import lombok.Data; -@RequiredArgsConstructor -public enum WikiSprite implements SpriteOverride +@Data +public class NpcInfo { - WIKI_ICON(-300, "wiki.png"), - WIKI_SELECTED_ICON(-301, "wiki_selected.png"), - FIXED_MODE_MINIMAP_CLICKMASK(SpriteID.MINIMAP_CLICK_MASK, "fixed_mode_minimap_clickmask.png"); - - @Getter(AccessLevel.PUBLIC) - private final int spriteId; - - @Getter(AccessLevel.PUBLIC) - private final String fileName; + private String name; + private int combat; + private int hitpoints; } diff --git a/http-api/src/main/java/net/runelite/http/api/npc/NpcInfoClient.java b/http-api/src/main/java/net/runelite/http/api/npc/NpcInfoClient.java new file mode 100644 index 0000000000..075b7b186a --- /dev/null +++ b/http-api/src/main/java/net/runelite/http/api/npc/NpcInfoClient.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2020, 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.http.api.npc; + +import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.util.Map; +import lombok.Value; +import lombok.extern.slf4j.Slf4j; +import net.runelite.http.api.RuneLiteAPI; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +@Slf4j +@Value +public class NpcInfoClient +{ + private final OkHttpClient client; + + public Map getNpcs() throws IOException + { + HttpUrl.Builder urlBuilder = RuneLiteAPI.getStaticBase().newBuilder() + .addPathSegment("npcs") + .addPathSegment("npcs.min.json"); + + HttpUrl url = urlBuilder.build(); + + log.debug("Built URI: {}", url); + + Request request = new Request.Builder() + .url(url) + .build(); + + try (Response response = client.newCall(request).execute()) + { + if (!response.isSuccessful()) + { + log.warn("Error looking up npcs: {}", response); + return null; + } + + InputStream in = response.body().byteStream(); + final Type typeToken = new TypeToken>() + { + }.getType(); + return RuneLiteAPI.GSON.fromJson(new InputStreamReader(in), typeToken); + } + catch (JsonParseException ex) + { + throw new IOException(ex); + } + } +} diff --git a/runelite-api/src/main/java/net/runelite/api/ItemID.java b/runelite-api/src/main/java/net/runelite/api/ItemID.java index c5a41c5673..79c4e4860a 100644 --- a/runelite-api/src/main/java/net/runelite/api/ItemID.java +++ b/runelite-api/src/main/java/net/runelite/api/ItemID.java @@ -11386,5 +11386,13 @@ public final class ItemID public static final int TWISTED_TELEPORT_SCROLL = 24460; public static final int TWISTED_BLUEPRINTS = 24463; public static final int TWISTED_HORNS = 24466; + public static final int TWISTED_RELICHUNTER_T1_ARMOUR_SET = 24469; + public static final int TWISTED_RELICHUNTER_T2_ARMOUR_SET = 24472; + public static final int TWISTED_RELICHUNTER_T3_ARMOUR_SET = 24475; + public static final int OPEN_HERB_SACK = 24478; + public static final int SPICE_RACK = 24479; + public static final int OPENED_COAL_BAG = 24480; + public static final int OPENED_GEM_BAG = 24481; + public static final int OPEN_SEED_BOX = 24482; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/NullItemID.java b/runelite-api/src/main/java/net/runelite/api/NullItemID.java index 261cb73dc0..0b4a9ee880 100644 --- a/runelite-api/src/main/java/net/runelite/api/NullItemID.java +++ b/runelite-api/src/main/java/net/runelite/api/NullItemID.java @@ -12874,5 +12874,11 @@ public final class NullItemID public static final int NULL_24465 = 24465; public static final int NULL_24467 = 24467; public static final int NULL_24468 = 24468; + public static final int NULL_24470 = 24470; + public static final int NULL_24471 = 24471; + public static final int NULL_24473 = 24473; + public static final int NULL_24474 = 24474; + public static final int NULL_24476 = 24476; + public static final int NULL_24477 = 24477; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/ObjectID.java b/runelite-api/src/main/java/net/runelite/api/ObjectID.java index 9a71d7f886..0b40375559 100644 --- a/runelite-api/src/main/java/net/runelite/api/ObjectID.java +++ b/runelite-api/src/main/java/net/runelite/api/ObjectID.java @@ -19534,5 +19534,7 @@ public final class ObjectID public static final int DOOR_HOTSPOT_37617 = 37617; public static final int DOOR_HOTSPOT_37618 = 37618; public static final int WINDOW_SPACE_37619 = 37619; + public static final int SPICE_RACK = 37620; + public static final int SPICE_RACK_37621 = 37621; /* This file is automatically generated. Do not edit. */ } diff --git a/runelite-api/src/main/java/net/runelite/api/SpriteID.java b/runelite-api/src/main/java/net/runelite/api/SpriteID.java index cde73ba3f8..839fbb1afb 100644 --- a/runelite-api/src/main/java/net/runelite/api/SpriteID.java +++ b/runelite-api/src/main/java/net/runelite/api/SpriteID.java @@ -1594,4 +1594,6 @@ public final class SpriteID public static final int HEALTHBAR_DEFAULT_BACK_140PX = 2189; public static final int HEALTHBAR_DEFAULT_FRONT_160PX = 2190; public static final int HEALTHBAR_DEFAULT_BACK_160PX = 2191; + public static final int WIKI_DESELECTED = 2420; + public static final int WIKI_SELECTED = 2421; } diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index cb05094726..c664425e9a 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -171,7 +171,7 @@ static class WorldMap static final int SEARCH = 24; static final int SURFACE_SELECTOR = 32; static final int TOOLTIP = 38; - static final int OPTION = 43; + static final int OPTION = 46; } static class SlayerRewards @@ -342,6 +342,7 @@ static class Minimap static final int RUN_ORB_TEXT = 23; static final int SPEC_ORB = 28; static final int WORLDMAP_ORB = 41; + static final int WIKI_BANNER = 43; } static class LoginClickToPlayScreen @@ -1187,9 +1188,9 @@ static class JewelBox static class Options { - static final int MUSIC_SLIDER = 44; - static final int SOUND_EFFECT_SLIDER = 50; - static final int AREA_SOUND_SLIDER = 56; + static final int MUSIC_SLIDER = 38; + static final int SOUND_EFFECT_SLIDER = 44; + static final int AREA_SOUND_SLIDER = 50; } static class AchievementDiary diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index d4bfeb2a07..e7c426defd 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -163,6 +163,7 @@ public enum WidgetInfo MINIMAP_SPEC_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.SPEC_ORB), MINIMAP_WORLDMAP_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WORLDMAP_ORB), MINIMAP_WORLD_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WORLDMAP_ORB), + MINIMAP_WIKI_BANNER(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.WIKI_BANNER), LMS_INFO(WidgetID.LMS_GROUP_ID, WidgetID.Lms.INFO), LMS_KDA(WidgetID.LMS_INGAME_GROUP_ID, WidgetID.LmsKDA.INFO), 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 a0d6d3d50a..3f7c821000 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 @@ -94,6 +94,7 @@ public class ChatCommandsPlugin extends Plugin { private static final Pattern KILLCOUNT_PATTERN = Pattern.compile("Your (.+) (?:kill|harvest|lap|completion) count is: (\\d+)"); private static final Pattern RAIDS_PATTERN = Pattern.compile("Your completed (.+) count is: (\\d+)"); + private static final Pattern RAIDS_DURATION_PATTERN = Pattern.compile("Congratulations - your raid is complete! Duration ([0-9:]+)"); private static final Pattern WINTERTODT_PATTERN = Pattern.compile("Your subdued Wintertodt count is: (\\d+)"); private static final Pattern BARROWS_PATTERN = Pattern.compile("Your Barrows chest count is: (\\d+)"); private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("(?i)^(?:Fight |Lap |Challenge |Corrupted challenge )?duration: [0-9:]+\\. Personal best: ([0-9:]+)"); @@ -452,6 +453,17 @@ void onChatMessage(ChatMessage chatMessage) int kc = Integer.parseInt(matcher.group(2)); setKc(boss, kc); + if (lastPb > -1) + { + // lastPb contains the last raid duration and not the personal best, because the raid + // complete message does not include the pb. We have to check if it is a new pb: + int currentPb = getPb(boss); + if (currentPb <= 0 || lastPb < currentPb) + { + setPb(boss, lastPb); + } + lastPb = -1; + } lastBossKill = boss; return; } @@ -513,29 +525,44 @@ else if (result.equals("were defeated")) matchPb(matcher); } + matcher = RAIDS_DURATION_PATTERN.matcher(message); + if (matcher.find()) + { + matchPb(matcher); + } + lastBossKill = null; } + private static int timeStringToSeconds(String timeString) + { + String[] s = timeString.split(":"); + if (s.length == 2) // mm:ss + { + return Integer.parseInt(s[0]) * 60 + Integer.parseInt(s[1]); + } + else if (s.length == 3) // h:mm:ss + { + return Integer.parseInt(s[0]) * 60 * 60 + Integer.parseInt(s[1]) * 60 + Integer.parseInt(s[2]); + } + return Integer.parseInt(timeString); + } + private void matchPb(Matcher matcher) { - String personalBest = matcher.group(1); - String[] s = personalBest.split(":"); - if (s.length == 2) + int seconds = timeStringToSeconds(matcher.group(1)); + if (lastBossKill != null) { - int seconds = Integer.parseInt(s[0]) * 60 + Integer.parseInt(s[1]); - if (lastBossKill != null) - { - // Most bosses sent boss kill message, and then pb message, so we - // use the remembered lastBossKill - log.debug("Got personal best for {}: {}", lastBossKill, seconds); - setPb(lastBossKill, seconds); - lastPb = -1; - } - else - { - // Some bosses send the pb message, and then the kill message! - lastPb = seconds; - } + // Most bosses sent boss kill message, and then pb message, so we + // use the remembered lastBossKill + log.debug("Got personal best for {}: {}", lastBossKill, seconds); + setPb(lastBossKill, seconds); + lastPb = -1; + } + else + { + // Some bosses send the pb message, and then the kill message! + lastPb = seconds; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java index e31de55d56..868d8b2a83 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiPlugin.java @@ -24,7 +24,6 @@ */ package net.runelite.client.plugins.wiki; -import com.google.common.primitives.Ints; import javax.inject.Inject; import javax.inject.Provider; import lombok.extern.slf4j.Slf4j; @@ -34,9 +33,11 @@ import net.runelite.api.NPC; import net.runelite.api.NPCDefinition; import net.runelite.api.ObjectDefinition; +import net.runelite.api.SpriteID; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.MenuOptionClicked; +import net.runelite.api.events.WidgetHiddenChanged; import net.runelite.api.events.WidgetLoaded; import net.runelite.api.util.Text; import net.runelite.api.widgets.JavaScriptCallback; @@ -104,14 +105,12 @@ public class WikiPlugin extends Plugin @Override public void startUp() { - spriteManager.addSpriteOverrides(WikiSprite.values()); clientThread.invokeLater(this::addWidgets); } @Override public void shutDown() { - spriteManager.removeSpriteOverrides(WikiSprite.values()); clientThread.invokeLater(() -> { Widget minimapOrbs = client.getWidget(WidgetInfo.MINIMAP_ORBS); @@ -126,6 +125,12 @@ public void shutDown() } children[0] = null; + Widget vanilla = client.getWidget(WidgetInfo.MINIMAP_WIKI_BANNER); + if (vanilla != null) + { + vanilla.setHidden(false); + } + onDeselect(); client.setSpellSelected(false); }); @@ -148,14 +153,20 @@ private void addWidgets() return; } + Widget vanilla = client.getWidget(WidgetInfo.MINIMAP_WIKI_BANNER); + if (vanilla != null) + { + vanilla.setHidden(true); + } + icon = minimapOrbs.createChild(0, WidgetType.GRAPHIC); - icon.setSpriteId(WikiSprite.WIKI_ICON.getSpriteId()); + icon.setSpriteId(SpriteID.WIKI_DESELECTED); icon.setOriginalX(0); - icon.setOriginalY(2); + icon.setOriginalY(0); icon.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT); icon.setYPositionMode(WidgetPositionMode.ABSOLUTE_BOTTOM); - icon.setOriginalWidth(42); - icon.setOriginalHeight(16); + icon.setOriginalWidth(40); + icon.setOriginalHeight(14); icon.setTargetVerb("Lookup"); icon.setName("Wiki"); icon.setClickMask(WidgetConfig.USE_GROUND_ITEM | WidgetConfig.USE_ITEM | WidgetConfig.USE_NPC @@ -164,7 +175,7 @@ private void addWidgets() icon.setOnTargetEnterListener((JavaScriptCallback) ev -> { wikiSelected = true; - icon.setSpriteId(WikiSprite.WIKI_SELECTED_ICON.getSpriteId()); + icon.setSpriteId(SpriteID.WIKI_SELECTED); client.setAllWidgetsAreOpTargetable(true); }); icon.setAction(5, "Search"); // Start at option 5 so the target op is ontop @@ -180,6 +191,15 @@ private void addWidgets() icon.revalidate(); } + @Subscribe + private void onWidgetHiddenChanged(WidgetHiddenChanged ev) + { + if (ev.getWidget().getId() == WidgetInfo.MINIMAP_WIKI_BANNER.getId()) + { + ev.getWidget().setHidden(true); + } + } + private void onDeselect() { client.setAllWidgetsAreOpTargetable(false); @@ -187,7 +207,7 @@ private void onDeselect() wikiSelected = false; if (icon != null) { - icon.setSpriteId(WikiSprite.WIKI_ICON.getSpriteId()); + icon.setSpriteId(SpriteID.WIKI_DESELECTED); } } @@ -352,59 +372,6 @@ private void onMenuEntryAdded(MenuEntryAdded event) } } - if (Ints.contains(QUESTLIST_WIDGET_IDS, widgetID) - && ((wikiSelected && widgetIndex != -1) || "Read Journal:".equals(event.getOption()))) - { - Widget w = getWidget(widgetID, widgetIndex); - String target = w.getName(); - - client.insertMenuItem( - MENUOP_QUICKGUIDE, - target, - MenuOpcode.RUNELITE.getId(), - 0, - widgetIndex, - widgetID, - false - ); - - client.insertMenuItem( - MENUOP_GUIDE, - target, - MenuOpcode.RUNELITE.getId(), - 0, - widgetIndex, - widgetID, - false - ); - } - - if (widgetID == WidgetInfo.ACHIEVEMENT_DIARY_CONTAINER.getId() - && event.getOption().contains("Open")) - { - Widget w = getWidget(widgetID, widgetIndex); - if (w.getActions() == null) - { - return; - } - - String action = firstAction(w); - if (action == null) - { - return; - } - - client.insertMenuItem( - MENUOP_WIKI, - action.replace("Open ", "").replace("Journal", "Diary"), - MenuOpcode.RUNELITE.getId(), - 0, - widgetIndex, - widgetID, - false - ); - } - if (WidgetInfo.TO_GROUP(widgetID) == WidgetInfo.SKILLS_CONTAINER.getGroupId() && event.getOption().contains("View")) { diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java index e68855b68e..3a2704f30a 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java @@ -612,21 +612,17 @@ public void requestFocus() { OSXUtil.requestFocus(); } - // The workaround for Windows is to minimise and then un-minimise the client to bring - // it to the front because java.awt.Window#toFront doesn't work reliably. + // See https://stackoverflow.com/questions/309023/how-to-bring-a-window-to-the-front/7435722#7435722 else if (OSType.getOSType() == OSType.Windows && !frame.isFocused()) { - if ((frame.getExtendedState() & JFrame.MAXIMIZED_BOTH) == JFrame.MAXIMIZED_BOTH) + SwingUtilities.invokeLater(() -> { - SwingUtilities.invokeLater(() -> + if ((frame.getExtendedState() & JFrame.MAXIMIZED_BOTH) == JFrame.MAXIMIZED_BOTH) { frame.setExtendedState(JFrame.ICONIFIED); frame.setExtendedState(JFrame.MAXIMIZED_BOTH); - }); - } - else - { - SwingUtilities.invokeLater(() -> + } + else { // If the client is snapped to the top and bottom edges of the screen, setExtendedState will // will reset it so setSize and setLocation ensure that the client doesn't move or resize. @@ -639,8 +635,8 @@ else if (OSType.getOSType() == OSType.Windows && !frame.isFocused()) frame.setExtendedState(JFrame.NORMAL); frame.setLocation(x, y); frame.setSize(width, height); - }); - } + } + }); } frame.requestFocus(); diff --git a/runelite-client/src/main/resources/item_variations.json b/runelite-client/src/main/resources/item_variations.json index ec379715fd..286bb1b40d 100644 --- a/runelite-client/src/main/resources/item_variations.json +++ b/runelite-client/src/main/resources/item_variations.json @@ -9676,5 +9676,10 @@ 24438, 24439, 24440 + ], + "twisted relichunter armour set": [ + 24469, + 24472, + 24475 ] } diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/fixed_mode_minimap_clickmask.png b/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/fixed_mode_minimap_clickmask.png deleted file mode 100644 index ba5a23c151..0000000000 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/fixed_mode_minimap_clickmask.png and /dev/null differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/wiki.png b/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/wiki.png deleted file mode 100644 index ef2ff20ff0..0000000000 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/wiki.png and /dev/null differ diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/wiki_selected.png b/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/wiki_selected.png deleted file mode 100644 index 80838fb5c4..0000000000 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/wiki/wiki_selected.png and /dev/null differ diff --git a/runelite-client/src/main/scripts/ClanChatChannelRebuild.hash b/runelite-client/src/main/scripts/ClanChatChannelRebuild.hash new file mode 100644 index 0000000000..e9601457f1 --- /dev/null +++ b/runelite-client/src/main/scripts/ClanChatChannelRebuild.hash @@ -0,0 +1 @@ +C70BDF62710D9FC0EB6707BD94FC0C4335B428DEDD1B52DD51776F811F32C9CF \ No newline at end of file diff --git a/runelite-client/src/main/scripts/ClanChatChannelRebuild.rs2asm b/runelite-client/src/main/scripts/ClanChatChannelRebuild.rs2asm new file mode 100644 index 0000000000..0724ae0048 --- /dev/null +++ b/runelite-client/src/main/scripts/ClanChatChannelRebuild.rs2asm @@ -0,0 +1,802 @@ +.id 1658 +.int_stack_count 15 +.string_stack_count 0 +.int_var_count 25 +.string_var_count 1 +; Callback "clanChatChannelRebuild" for whenever clan chat is done being built, used inside ClanChatPlugin for ignores + iload 3 + iconst 6 + iconst 7 + iconst 6 + sconst "Sort by rank" + iload 0 + iload 1 + iload 2 + iload 3 + iload 4 + iload 5 + iload 6 + iload 7 + iload 8 + iload 9 + iload 10 + iload 11 + iload 12 + iload 13 + iload 14 + invoke 1659 + iload 4 + iconst 2 + iconst 3 + iconst 2 + sconst "Sort by name" + iload 0 + iload 1 + iload 2 + iload 3 + iload 4 + iload 5 + iload 6 + iload 7 + iload 8 + iload 9 + iload 10 + iload 11 + iload 12 + iload 13 + iload 14 + invoke 1659 + iload 5 + iconst 8 + iconst 9 + iconst 9 + sconst "Sort by last world change" + iload 0 + iload 1 + iload 2 + iload 3 + iload 4 + iload 5 + iload 6 + iload 7 + iload 8 + iload 9 + iload 10 + iload 11 + iload 12 + iload 13 + iload 14 + invoke 1659 + iload 6 + iconst 4 + iconst 5 + iconst 4 + sconst "Sort by world" + iload 0 + iload 1 + iload 2 + iload 3 + iload 4 + iload 5 + iload 6 + iload 7 + iload 8 + iload 9 + iload 10 + iload 11 + iload 12 + iload 13 + iload 14 + invoke 1659 + iload 7 + iconst 0 + iconst 1 + iconst 0 + sconst "Legacy sort" + iload 0 + iload 1 + iload 2 + iload 3 + iload 4 + iload 5 + iload 6 + iload 7 + iload 8 + iload 9 + iload 10 + iload 11 + iload 12 + iload 13 + iload 14 + invoke 1659 + 3644 + get_varc_int 185 + switch + 1: LABEL109 + 2: LABEL112 + 3: LABEL115 + 4: LABEL184 + 5: LABEL212 + 6: LABEL118 + 7: LABEL148 + 8: LABEL178 + 9: LABEL181 + jump LABEL239 +LABEL109: + iconst 0 + 3645 + jump LABEL239 +LABEL112: + iconst 1 + 3646 + jump LABEL239 +LABEL115: + iconst 0 + 3646 + jump LABEL239 +LABEL118: + iconst 1 + 3657 + get_varc_int 206 + switch + 3: LABEL125 + 4: LABEL128 + 5: LABEL135 + 8: LABEL142 + 9: LABEL145 + iconst 1 + 3646 + jump LABEL147 +LABEL125: + iconst 0 + 3646 + jump LABEL147 +LABEL128: + iconst 1 + 3652 + iconst 1 + 3647 + iconst 1 + 3646 + jump LABEL147 +LABEL135: + iconst 1 + 3652 + iconst 0 + 3647 + iconst 1 + 3646 + jump LABEL147 +LABEL142: + iconst 1 + 3648 + jump LABEL147 +LABEL145: + iconst 0 + 3648 +LABEL147: + jump LABEL239 +LABEL148: + iconst 0 + 3657 + get_varc_int 206 + switch + 3: LABEL155 + 4: LABEL158 + 5: LABEL165 + 8: LABEL172 + 9: LABEL175 + iconst 1 + 3646 + jump LABEL177 +LABEL155: + iconst 0 + 3646 + jump LABEL177 +LABEL158: + iconst 1 + 3652 + iconst 1 + 3647 + iconst 1 + 3646 + jump LABEL177 +LABEL165: + iconst 1 + 3652 + iconst 0 + 3647 + iconst 1 + 3646 + jump LABEL177 +LABEL172: + iconst 1 + 3648 + jump LABEL177 +LABEL175: + iconst 0 + 3648 +LABEL177: + jump LABEL239 +LABEL178: + iconst 1 + 3648 + jump LABEL239 +LABEL181: + iconst 0 + 3648 + jump LABEL239 +LABEL184: + iconst 1 + 3652 + iconst 1 + 3647 + get_varc_int 206 + switch + 3: LABEL193 + 6: LABEL196 + 7: LABEL201 + 8: LABEL206 + 9: LABEL209 + iconst 1 + 3646 + jump LABEL211 +LABEL193: + iconst 0 + 3646 + jump LABEL211 +LABEL196: + iconst 1 + 3657 + iconst 1 + 3646 + jump LABEL211 +LABEL201: + iconst 0 + 3657 + iconst 1 + 3646 + jump LABEL211 +LABEL206: + iconst 1 + 3648 + jump LABEL211 +LABEL209: + iconst 0 + 3648 +LABEL211: + jump LABEL239 +LABEL212: + iconst 1 + 3652 + iconst 0 + 3647 + get_varc_int 206 + switch + 3: LABEL221 + 6: LABEL224 + 7: LABEL229 + 8: LABEL234 + 9: LABEL237 + iconst 1 + 3646 + jump LABEL239 +LABEL221: + iconst 0 + 3646 + jump LABEL239 +LABEL224: + iconst 1 + 3657 + iconst 1 + 3646 + jump LABEL239 +LABEL229: + iconst 0 + 3657 + iconst 1 + 3646 + jump LABEL239 +LABEL234: + iconst 1 + 3648 + jump LABEL239 +LABEL237: + iconst 0 + 3648 +LABEL239: + 3655 + iload 8 + cc_deleteall + clan_getchatcount + istore 15 + get_varbit 6363 + iconst 1 + if_icmpeq LABEL248 + jump LABEL296 +LABEL248: + iload 15 + iconst 0 + if_icmpgt LABEL252 + jump LABEL253 +LABEL252: + clan_leavechat +LABEL253: + iconst 0 + istore 15 + iconst 0 + iload 2 + if_sethide + iconst 1 + iload 9 + if_sethide + iload 11 + invoke 2067 + pop_int + iconst -1 + sconst "" + iload 11 + if_setonmouserepeat + iconst -1 + sconst "" + iload 11 + if_setonmouseleave + iload 13 + invoke 2067 + pop_int + iconst -1 + sconst "" + iload 13 + if_setonmouserepeat + iconst -1 + sconst "" + iload 13 + if_setonmouseleave + sconst "" + sconst "---" + sconst "" + join_string 3 + iload 12 + if_settext + iload 12 + if_clearops + iconst -1 + sconst "" + iload 12 + if_setonop + jump LABEL341 +LABEL296: + iconst 1 + iload 2 + if_sethide + iconst 0 + iload 9 + if_sethide + iload 11 + invoke 486 + pop_int + iconst 94 + iconst -2147483645 + sconst "I" + iload 11 + if_setonmouserepeat + iconst 92 + iconst -2147483645 + sconst "I" + iload 11 + if_setonmouseleave + iload 13 + invoke 486 + pop_int + iconst 94 + iconst -2147483645 + sconst "I" + iload 13 + if_setonmouserepeat + iconst 92 + iconst -2147483645 + sconst "I" + iload 13 + if_setonmouseleave + sconst "Clan Setup" + iload 12 + if_settext + iconst 1 + sconst "Clan Setup" + iload 12 + if_setop + iconst 489 + iconst -2147483644 + iconst 1 + sconst "ii" + iload 12 + if_setonop +LABEL341: + sconst "" + sstore 0 + iconst -1 + istore 16 + iconst -1 + istore 17 + clan_getchatrank + istore 18 + clan_getchatminkick + istore 19 + iload 3 + if_getwidth + istore 20 + iconst 0 + istore 21 + iconst 0 + istore 22 + iconst 15 + istore 23 + invoke 1972 + iconst 1 + if_icmpeq LABEL364 + jump LABEL369 +LABEL364: + iconst 8 + iconst 5 + iload 23 + scale + istore 23 +LABEL369: + iconst 0 + istore 24 +LABEL371: + iload 24 + iload 15 + if_icmplt LABEL375 + jump LABEL572 +LABEL375: + iload 24 + clan_getchatusername + iload 24 + clan_getchatuserworld + iload 24 + clan_getchatuserrank + istore 17 + istore 16 + sstore 0 + iload 8 + iconst 4 + iload 21 + cc_create + iload 21 + iconst 1 + add + istore 21 + iload 20 + iload 23 + iconst 1 + iconst 0 + cc_setsize + iconst 0 + iload 22 + iconst 2 + iconst 0 + cc_setposition + iconst 494 + cc_settextfont + iconst 0 + iconst 1 + iconst 0 + cc_settextalign + sload 0 + cc_settext + iconst 16777215 + cc_setcolour + iconst 0 + cc_settextshadow + iload 8 + iconst 4 + iload 21 + cc_create 1 + iload 21 + iconst 1 + add + istore 21 + iload 20 + iload 23 + iconst 1 + iconst 0 + cc_setsize 1 + iconst 0 + iload 22 + iconst 2 + iconst 0 + cc_setposition 1 + iconst 494 + cc_settextfont 1 + iconst 2 + iconst 1 + iconst 0 + cc_settextalign 1 + sconst "World " + iload 16 + tostring + join_string 2 + cc_settext 1 + iload 16 + map_world + if_icmpeq LABEL447 + jump LABEL450 +LABEL447: + iconst 901389 + cc_setcolour 1 + jump LABEL452 +LABEL450: + iconst 16777060 + cc_setcolour 1 +LABEL452: + iconst 0 + cc_settextshadow 1 + iload 8 + iconst 5 + iload 21 + cc_create 1 + iload 21 + iconst 1 + add + istore 21 + iconst 9 + iconst 9 + iconst 0 + iconst 0 + cc_setsize 1 + iconst 1 + iload 22 + iload 23 + iconst 9 + sub + iconst 2 + div + add + iconst 0 + iconst 0 + cc_setposition 1 + iconst 105 + iconst 100 + iconst 706 + iload 17 + enum + cc_setgraphic 1 + iload 24 + clan_isself + iconst 0 + if_icmpeq LABEL489 + jump LABEL525 +LABEL489: + iload 24 + clan_isfriend + iconst 1 + if_icmpeq LABEL494 + jump LABEL501 +LABEL494: + iconst 9 + sconst "Remove friend" + cc_setop + iconst 9 + sconst "Remove friend" + cc_setop 1 + jump LABEL525 +LABEL501: + iload 24 + clan_isignore + iconst 1 + if_icmpeq LABEL506 + jump LABEL513 +LABEL506: + iconst 10 + sconst "Remove ignore" + cc_setop + iconst 10 + sconst "Remove ignore" + cc_setop 1 + jump LABEL525 +LABEL513: + iconst 7 + sconst "Add friend" + cc_setop + iconst 7 + sconst "Add friend" + cc_setop 1 + iconst 8 + sconst "Add ignore" + cc_setop + iconst 8 + sconst "Add ignore" + cc_setop 1 +LABEL525: + invoke 1942 + iconst 0 + if_icmpeq LABEL529 + jump LABEL543 +LABEL529: + iload 18 + iload 19 + if_icmpge LABEL533 + jump LABEL543 +LABEL533: + iload 18 + iload 17 + if_icmpgt LABEL537 + jump LABEL543 +LABEL537: + iconst 6 + sconst "Kick user" + cc_setop + iconst 6 + sconst "Kick user" + cc_setop 1 +LABEL543: + sconst "" + sload 0 + sconst "" + join_string 3 + cc_setopbase + sconst "" + sload 0 + sconst "" + join_string 3 + cc_setopbase 1 + iconst 214 + sconst "event_opbase" + iconst -2147483644 + sconst "si" + cc_setonop + iconst 214 + sconst "event_opbase" + iconst -2147483644 + sconst "si" + cc_setonop 1 + iload 24 + iconst 1 + add + iload 22 + iload 23 + add + istore 22 + istore 24 + jump LABEL371 +LABEL572: + iload 15 + iconst 1 + if_icmpge LABEL576 + jump LABEL580 +LABEL576: + iload 22 + iconst 5 + add + istore 22 +LABEL580: + iload 10 + if_clearops + get_varbit 6363 + iconst 1 + if_icmpeq LABEL586 + jump LABEL605 +LABEL586: + sconst "" + iload 0 + if_settext + sconst "" + iload 1 + if_settext + sconst "" + sconst "---" + sconst "" + join_string 3 + iload 10 + if_settext + iload 10 + if_clearops + iconst -1 + sconst "" + iload 10 + if_setonop + jump LABEL672 +LABEL605: + iload 15 + iconst 0 + if_icmpgt LABEL609 + jump LABEL653 +LABEL609: + sconst "" + clan_getchatdisplayname + sconst "" + join_string 3 + iload 0 + if_settext + sconst "" + clan_getchatownername + sconst "" + join_string 3 + iload 1 + if_settext + sconst "Leave Chat" + iload 10 + if_settext + get_varbit 5432 + iconst 1 + if_icmpeq LABEL631 + get_varbit 4289 + iconst 0 + if_icmpne LABEL631 + jump LABEL642 +LABEL631: + iconst 6 + sconst "Leave Chat" + iload 10 + if_setop + iconst 194 + iconst -2147483644 + iconst 6 + sconst "ii" + iload 10 + if_setonop + jump LABEL652 +LABEL642: + iconst 1 + sconst "Leave Chat" + iload 10 + if_setop + iconst 194 + iconst -2147483644 + iconst 1 + sconst "ii" + iload 10 + if_setonop +LABEL652: + jump LABEL672 +LABEL653: + sconst "Not in chat" + iload 0 + if_settext + sconst "None" + iload 1 + if_settext + sconst "Join Chat" + iload 10 + if_settext + iconst 1 + sconst "Join Chat" + iload 10 + if_setop + iconst 194 + iconst -2147483644 + iconst 1 + sconst "ii" + iload 10 + if_setonop +LABEL672: + iload 22 + iload 8 + if_getheight + if_icmpgt LABEL677 + jump LABEL687 +LABEL677: + iconst 0 + iload 22 + iload 8 + if_setscrollsize + iload 9 + iload 8 + iload 8 + if_getscrolly + invoke 72 + jump LABEL695 +LABEL687: + iconst 0 + iconst 0 + iload 8 + if_setscrollsize + iload 9 + iload 8 + iconst 0 + invoke 72 +LABEL695: + sconst "clanChatChannelRebuild" + runelite_callback + return diff --git a/runelite-client/src/main/scripts/CommandScript.hash b/runelite-client/src/main/scripts/CommandScript.hash index c278c005ee..aba3b74962 100644 --- a/runelite-client/src/main/scripts/CommandScript.hash +++ b/runelite-client/src/main/scripts/CommandScript.hash @@ -1 +1 @@ -2F7E219C24E4725FA8F3BCDD9F2A640666CC589B514FEBD9F5938B207F06C0EB \ No newline at end of file +1E915795AFAA25E3ABE595EEAC55423C3E5E9E5CE2582AD1A5AAEC91647CC124 \ No newline at end of file diff --git a/runelite-client/src/main/scripts/CommandScript.rs2asm b/runelite-client/src/main/scripts/CommandScript.rs2asm index 930256d55e..6a07580ada 100644 --- a/runelite-client/src/main/scripts/CommandScript.rs2asm +++ b/runelite-client/src/main/scripts/CommandScript.rs2asm @@ -39,7 +39,7 @@ LABEL20: if_icmpeq LABEL31 iconst 0 ; Modified to enable clanchat input sconst "clanchatInput" - runelite_callback + runelite_callback iconst 1 if_icmpeq LABEL31 ; Compare to 1 jump LABEL37 @@ -82,13 +82,13 @@ LABEL58: iload 0 iconst 84 if_icmpeq LABEL62 - jump LABEL179 + jump LABEL189 LABEL62: invoke 1984 iload 2 iconst 0 if_icmpgt LABEL67 - jump LABEL178 + jump LABEL188 LABEL67: get_varc_string 335 sconst "/" @@ -146,7 +146,7 @@ LABEL108: iconst 0 invoke 96 LABEL111: - jump LABEL174 + jump LABEL184 LABEL112: get_varc_string 335 sconst "::" @@ -154,12 +154,12 @@ LABEL112: string_indexof_string iconst 0 if_icmpeq LABEL119 - jump LABEL171 + jump LABEL181 LABEL119: iload 2 iconst 2 if_icmpgt LABEL123 - jump LABEL167 + jump LABEL177 LABEL123: get_varc_string 335 sconst "::toggleroof" @@ -185,23 +185,35 @@ LABEL139: sconst "Roofs are now all hidden." mes LABEL143: - jump LABEL166 + jump LABEL176 LABEL144: get_varc_string 335 - sconst "::bank" + sconst "::wiki" iconst 0 string_indexof_string iconst 0 if_icmpeq LABEL151 sconst "runeliteCommand" ; load callback name runelite_callback ; invoke callback - jump LABEL155 + jump LABEL154 LABEL151: + get_varc_string 335 + invoke 3299 + jump LABEL176 +LABEL154: + get_varc_string 335 + sconst "::bank" + iconst 0 + string_indexof_string + iconst 0 + if_icmpeq LABEL161 + jump LABEL165 +LABEL161: sconst "Hey, everyone, I just tried to do something very silly!" iconst 0 invoke 96 - jump LABEL166 -LABEL155: + jump LABEL176 +LABEL165: get_varc_string 335 invoke 224 set_varc_string 335 @@ -213,42 +225,28 @@ LABEL155: iload 2 substring docheat -LABEL166: - jump LABEL170 -LABEL167: +LABEL176: + jump LABEL180 +LABEL177: get_varc_string 335 iconst 0 invoke 96 -LABEL170: - jump LABEL174 -LABEL171: +LABEL180: + jump LABEL184 +LABEL181: get_varc_string 335 iconst 0 invoke 96 -LABEL174: +LABEL184: get_varc_string 335 invoke 77 sconst "" set_varc_string 335 -LABEL178: - jump LABEL247 -LABEL179: - iload 0 - iconst 104 - if_icmpeq LABEL183 - jump LABEL189 -LABEL183: - iload 3 - iconst 1 - if_icmpeq LABEL187 - jump LABEL188 -LABEL187: - invoke 75 LABEL188: - jump LABEL247 + jump LABEL257 LABEL189: iload 0 - iconst 105 + iconst 104 if_icmpeq LABEL193 jump LABEL199 LABEL193: @@ -257,38 +255,52 @@ LABEL193: if_icmpeq LABEL197 jump LABEL198 LABEL197: - invoke 76 + invoke 75 LABEL198: - jump LABEL247 + jump LABEL257 LABEL199: iload 0 - iconst 80 + iconst 105 if_icmpeq LABEL203 - jump LABEL241 + jump LABEL209 LABEL203: + iload 3 + iconst 1 + if_icmpeq LABEL207 + jump LABEL208 +LABEL207: + invoke 76 +LABEL208: + jump LABEL257 +LABEL209: + iload 0 + iconst 80 + if_icmpeq LABEL213 + jump LABEL251 +LABEL213: get_varc_string 356 string_length iconst 0 - if_icmpgt LABEL208 - jump LABEL228 -LABEL208: + if_icmpgt LABEL218 + jump LABEL238 +LABEL218: get_varc_string 356 friend_test iconst 1 - if_icmpeq LABEL213 - jump LABEL216 -LABEL213: + if_icmpeq LABEL223 + jump LABEL226 +LABEL223: get_varc_string 356 invoke 107 return -LABEL216: +LABEL226: get_varc_int 60 clientclock - if_icmpgt LABEL220 - jump LABEL221 -LABEL220: + if_icmpgt LABEL230 + jump LABEL231 +LABEL230: return -LABEL221: +LABEL231: clientclock iconst 50 add @@ -296,14 +308,14 @@ LABEL221: sconst "That player was not found on your Friends list." mes return -LABEL228: +LABEL238: get_varc_int 60 clientclock - if_icmpgt LABEL232 - jump LABEL233 -LABEL232: + if_icmpgt LABEL242 + jump LABEL243 +LABEL242: return -LABEL233: +LABEL243: clientclock iconst 50 add @@ -311,8 +323,8 @@ LABEL233: sconst "You haven't received any messages to which you can reply." mes return - jump LABEL247 -LABEL241: + jump LABEL257 +LABEL251: get_varc_string 335 iconst 0 iload 0 @@ -324,9 +336,9 @@ LABEL241: runelite_callback ; if_icmpeq SKIPSETVARC ; skip setting varc with input set_varc_string 335 - jump LABEL247 ; jump over SKIPSETVARC + jump LABEL257 ; jump over SKIPSETVARC SKIPSETVARC: - pop_string ; pop message -LABEL247: + pop_string ; pop message +LABEL257: invoke 223 return diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java index 2774f5cad8..d3e5d0a562 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java @@ -39,8 +39,12 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import org.mockito.Mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.mockito.junit.MockitoJUnitRunner; @@ -361,4 +365,35 @@ public void testGuantletNewPersonalBest() verify(configManager).setConfiguration(eq("personalbest.adam"), eq("gauntlet"), eq(10 * 60 + 24)); verify(configManager).setConfiguration(eq("killcount.adam"), eq("gauntlet"), eq(124)); } + + @Test + public void testCoXKill() + { + when(client.getUsername()).thenReturn("Adam"); + + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Congratulations - your raid is complete! Duration 37:04", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: 51.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setConfiguration(eq("killcount.adam"), eq("chambers of xeric"), eq(51)); + verify(configManager).setConfiguration(eq("personalbest.adam"), eq("chambers of xeric"), eq(37 * 60 + 4)); + } + + @Test + public void testCoXKillNoPb() + { + when(client.getUsername()).thenReturn("Adam"); + when(configManager.getConfiguration(anyString(), anyString(), any())).thenReturn(2224); + + ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Congratulations - your raid is complete! Duration 1:45:04", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: 52.", null, 0); + chatCommandsPlugin.onChatMessage(chatMessage); + + verify(configManager).setConfiguration(eq("killcount.adam"), eq("chambers of xeric"), eq(52)); + verify(configManager, never()).setConfiguration(eq("personalbest.adam"), eq("chambers of xeric"), anyInt()); + } }