diff --git a/runelite-api/src/main/java/net/runelite/api/ItemComposition.java b/runelite-api/src/main/java/net/runelite/api/ItemComposition.java index fcd0ce25a0..235e3dbef8 100644 --- a/runelite-api/src/main/java/net/runelite/api/ItemComposition.java +++ b/runelite-api/src/main/java/net/runelite/api/ItemComposition.java @@ -133,13 +133,6 @@ public interface ItemComposition extends ParamHolder */ void resetShiftClickActionIndex(); - /** - * With this you can make certain (ground) items look like different ones. - * - * @param id The itemID of the item with desired model - */ - void setModelOverride(int id); - /** * Gets the model ID of the inventory item. * 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 5fe1f111e9..556bcbf8f0 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -145,6 +145,7 @@ import net.runelite.rs.api.RSChatChannel; import net.runelite.rs.api.RSClanChannel; import net.runelite.rs.api.RSClient; import net.runelite.rs.api.RSEnumComposition; +import net.runelite.rs.api.RSEvictingDualNodeHashTable; import net.runelite.rs.api.RSFriendSystem; import net.runelite.rs.api.RSIndexedSprite; import net.runelite.rs.api.RSInterfaceParent; @@ -1767,6 +1768,13 @@ public abstract class RSClientMixin implements RSClient updateCamera(); } + @Inject + @MethodHook(value = "draw", end = true) + public void drawEnd(boolean var1) + { + checkResize(); + } + @MethodHook("drawInterface") @Inject public static void preRenderWidgetLayer(Widget[] widgets, int parentId, int minX, int minY, int maxX, int maxY, int x, int y, int var8) @@ -2695,5 +2703,68 @@ public abstract class RSClientMixin implements RSClient { client.getCallbacks().tick(); } + + @Inject + public static void check(String name, RSEvictingDualNodeHashTable dualNodeHashTable) + { + boolean var3 = dualNodeHashTable.isTrashing(); + dualNodeHashTable.setThreshold(dualNodeHashTable.getThreshold() * 0.92F + (var3 ? 0.07999998F : 0.0F)); + if (var3) + { + if (dualNodeHashTable.getThreshold() > 0.2F) + { + client.getLogger().trace("cache {} is thrashing", name); + } + + if (dualNodeHashTable.getThreshold() > 0.9F && dualNodeHashTable.getCapacity() < dualNodeHashTable.getTmpCapacity() * 8) + { + dualNodeHashTable.increaseCapacity(dualNodeHashTable.getCapacity() * 2); + client.getLogger().info("cache {} thrashing, enlarging to {} entries", name, dualNodeHashTable.getCapacity()); + } + } + + dualNodeHashTable.getDeque().add(dualNodeHashTable.getDualNode()); + } + + @Inject + public static void checkResize() + { + check("Script_cached", client.getScriptCache()); + check("StructDefinition_cached", client.getRSStructCompositionCache()); + check("HealthBarDefinition_cached", client.getHealthBarCache()); + check("HealthBarDefinition_cachedSprites", client.getHealthBarSpriteCache()); + check("ObjectDefinition_cachedModels", client.getObjectDefinitionModelsCache()); + check("Widget_cachedSprites", client.getWidgetSpriteCache()); + check("ItemDefinition_cached", client.getItemCompositionCache()); + check("VarbitDefinition_cached", client.getVarbitCache()); + check("EnumDefinition_cached", client.getEnumDefinitionCache()); + check("FloorUnderlayDefinition_cached", client.getFloorUnderlayDefinitionCache()); + check("FloorOverlayDefinition_cached", client.getFloorOverlayDefinitionCache()); + check("HitSplatDefinition_cached", client.getHitSplatDefinitionCache()); + check("HitSplatDefinition_cachedSprites", client.getHitSplatDefinitionSpritesCache()); + check("HitSplatDefinition_cachedFonts", client.getHitSplatDefinitionDontsCache()); + check("InvDefinition_cached", client.getInvDefinitionCache()); + check("ItemDefinition_cachedModels", client.getItemDefinitionModelsCache()); + check("ItemDefinition_cachedSprites", client.getItemDefinitionSpritesCache()); + check("KitDefinition_cached", client.getKitDefinitionCache()); + check("NpcDefinition_cached", client.getNpcDefinitionCache()); + check("NpcDefinition_cachedModels", client.getNpcDefinitionModelsCache()); + check("ObjectDefinition_cached", client.getObjectDefinitionCache()); + check("ObjectDefinition_cachedModelData", client.getObjectDefinitionModelDataCache()); + check("ObjectDefinition_cachedEntities", client.getObjectDefinitionEntitiesCache()); + check("ParamDefinition_cached", client.getParamDefinitionCache()); + check("PlayerAppearance_cachedModels", client.getPlayerAppearanceModelsCache()); + check("SequenceDefinition_cached", client.getSequenceDefinitionCache()); + check("SequenceDefinition_cachedFrames", client.getSequenceDefinitionFramesCache()); + check("SequenceDefinition_cachedModel", client.getSequenceDefinitionModelsCache()); + check("SpotAnimationDefinition_cached", client.getSpotAnimationDefinitionCache()); + check("SpotAnimationDefinition_cachedModels", client.getSpotAnimationDefinitionModlesCache()); + check("VarcInt_cached", client.getVarcIntCache()); + check("VarpDefinition_cached", client.getVarpDefinitionCache()); + check("Widget_cachedModels", client.getModelsCache()); + check("Widget_cachedFonts", client.getFontsCache()); + check("Widget_cachedSpriteMasks", client.getSpriteMasksCache()); + check("WorldMapElement_cachedSprites", client.getSpritesCache()); + } } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSEvictingDualNodeHashTableMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSEvictingDualNodeHashTableMixin.java new file mode 100644 index 0000000000..bf14b36aa6 --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSEvictingDualNodeHashTableMixin.java @@ -0,0 +1,84 @@ +package net.runelite.mixins; + +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.Mixin; +import net.runelite.api.mixins.Shadow; +import net.runelite.rs.api.RSClient; +import net.runelite.rs.api.RSEvictingDualNodeHashTable; +import net.runelite.rs.api.RSIterableNodeHashTable; + +@Mixin(RSEvictingDualNodeHashTable.class) +public abstract class RSEvictingDualNodeHashTableMixin implements RSEvictingDualNodeHashTable +{ + @Shadow("client") + private static RSClient client; + + @Inject + public float threshold; + + @Inject + public int tmpCapacity; + + @Inject + RSEvictingDualNodeHashTableMixin() + { + setTmpCapacity(this.getCapacity()); + } + + @Inject + public float getThreshold() + { + return threshold; + } + + @Inject + public void setThreshold(float threshold) + { + this.threshold = threshold; + } + + @Inject + public int getTmpCapacity() + { + return tmpCapacity; + } + + @Inject + public void setTmpCapacity(int tmpCapacity) + { + this.tmpCapacity = tmpCapacity; + } + + @Inject + public boolean isTrashing() + { + return this.getRemainingCapacity() <= 0 && this.getDualNode().previousDual() == null; + } + + @Inject + public void resize(int newSize) + { + this.increaseCapacity(newSize); + this.tmpCapacity = this.getCapacity(); + } + + @Inject + public void increaseCapacity(int newSize) + { + if (newSize > this.getCapacity()) + { + int i; + + for (i = 1; i < newSize; i += i) + { + // ignore + } + + this.setCapacity(i); + this.reset(); + + RSIterableNodeHashTable iterableNodeHashTable = client.createIterableNodeHashTable(i); + this.setHashTable(iterableNodeHashTable); + } + } +} diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSItemCompositionMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSItemCompositionMixin.java index d9ff0bef2a..8662d5e513 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSItemCompositionMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSItemCompositionMixin.java @@ -8,8 +8,8 @@ import net.runelite.api.mixins.Mixin; import net.runelite.api.mixins.Replace; import net.runelite.api.mixins.Shadow; import net.runelite.rs.api.RSClient; +import net.runelite.rs.api.RSEvictingDualNodeHashTable; import net.runelite.rs.api.RSItemComposition; -import net.runelite.rs.api.RSModel; @Mixin(RSItemComposition.class) public abstract class RSItemCompositionMixin implements RSItemComposition @@ -22,19 +22,12 @@ public abstract class RSItemCompositionMixin implements RSItemComposition @Inject private int shiftClickActionIndex = DEFAULT_CUSTOM_SHIFT_CLICK_INDEX; + @MethodHook(value = "", end = true) @Inject - private int modelOverride = -1; - - @Override - @Inject - public void setModelOverride(int id) - { - modelOverride = id; - } - - @Inject - RSItemCompositionMixin() + public static void rl$clinit() { + RSEvictingDualNodeHashTable cachedModels2 = client.getItemCompositionCache(); + cachedModels2.resize(1024); } @Inject @@ -74,18 +67,6 @@ public abstract class RSItemCompositionMixin implements RSItemComposition client.getCallbacks().post(event); } - @Copy("getModel") - @Replace("getModel") - public RSModel copy$getModel(int quantity) - { - if (modelOverride == -1) - { - return copy$getModel(quantity); - } - - return client.getRSItemDefinition(modelOverride).getModel(quantity); - } - @Inject @Override public int getHaPrice() diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSObjectCompositionMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSObjectCompositionMixin.java index 8cb1da388f..22f0037936 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSObjectCompositionMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSObjectCompositionMixin.java @@ -2,10 +2,10 @@ package net.runelite.mixins; import net.runelite.api.IterableHashTable; import net.runelite.api.Node; -import net.runelite.api.NodeCache; import net.runelite.api.mixins.*; import net.runelite.rs.api.RSBuffer; import net.runelite.rs.api.RSClient; +import net.runelite.rs.api.RSEvictingDualNodeHashTable; import net.runelite.rs.api.RSObjectComposition; @Mixin(RSObjectComposition.class) @@ -17,14 +17,12 @@ public abstract class RSObjectCompositionMixin implements RSObjectComposition @Inject private int accessBitMask = 0; - @MethodHook(value = "", end = true) + @MethodHook(value = "", end = true) @Inject - public void rl$init() + public static void rl$clinit() { - NodeCache cachedModels2 = client.getCachedModels2(); - cachedModels2.setCapacity(256); - cachedModels2.setRemainingCapacity(256); - cachedModels2.reset(); + RSEvictingDualNodeHashTable objectDefinitionModelsCache = client.getObjectDefinitionModelsCache(); + objectDefinitionModelsCache.resize(256); } @Inject diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSVarbitCompositionMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSVarbitCompositionMixin.java new file mode 100644 index 0000000000..1e54531bde --- /dev/null +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSVarbitCompositionMixin.java @@ -0,0 +1,24 @@ +package net.runelite.mixins; + +import net.runelite.api.mixins.Inject; +import net.runelite.api.mixins.MethodHook; +import net.runelite.api.mixins.Mixin; +import net.runelite.api.mixins.Shadow; +import net.runelite.rs.api.RSClient; +import net.runelite.rs.api.RSEvictingDualNodeHashTable; +import net.runelite.rs.api.RSVarbitComposition; + +@Mixin(RSVarbitComposition.class) +public abstract class RSVarbitCompositionMixin implements RSVarbitComposition +{ + @Shadow("client") + private static RSClient client; + + @MethodHook(value = "", end = true) + @Inject + public static void rl$clinit() + { + RSEvictingDualNodeHashTable varbitCache = client.getVarbitCache(); + varbitCache.resize(256); + } +} 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 1cab3dd535..7efa44cba7 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 @@ -926,7 +926,7 @@ public interface RSClient extends RSGameEngine, Client int[][] getOccupiedTilesTick(); @Import("ObjectDefinition_cachedModels") - RSEvictingDualNodeHashTable getCachedModels2(); + RSEvictingDualNodeHashTable getObjectDefinitionModelsCache(); @Import("Scene_drawnCount") int getCycle(); @@ -1483,4 +1483,91 @@ public interface RSClient extends RSGameEngine, Client @Import("objectSounds") Deque getAmbientSoundEffects(); + + @Import("EnumDefinition_cached") + RSEvictingDualNodeHashTable getEnumDefinitionCache(); + + @Import("FloorUnderlayDefinition_cached") + RSEvictingDualNodeHashTable getFloorUnderlayDefinitionCache(); + + @Import("FloorOverlayDefinition_cached") + RSEvictingDualNodeHashTable getFloorOverlayDefinitionCache(); + + @Import("HitSplatDefinition_cached") + RSEvictingDualNodeHashTable getHitSplatDefinitionCache(); + + @Import("HitSplatDefinition_cachedSprites") + RSEvictingDualNodeHashTable getHitSplatDefinitionSpritesCache(); + + @Import("HitSplatDefinition_cachedFonts") + RSEvictingDualNodeHashTable getHitSplatDefinitionDontsCache(); + + @Import("InvDefinition_cached") + RSEvictingDualNodeHashTable getInvDefinitionCache(); + + @Import("ItemDefinition_cachedModels") + RSEvictingDualNodeHashTable getItemDefinitionModelsCache(); + + @Import("ItemDefinition_cachedSprites") + RSEvictingDualNodeHashTable getItemDefinitionSpritesCache(); + + @Import("KitDefinition_cached") + RSEvictingDualNodeHashTable getKitDefinitionCache(); + + @Import("NpcDefinition_cached") + RSEvictingDualNodeHashTable getNpcDefinitionCache(); + + @Import("NpcDefinition_cachedModels") + RSEvictingDualNodeHashTable getNpcDefinitionModelsCache(); + + @Import("ObjectDefinition_cached") + RSEvictingDualNodeHashTable getObjectDefinitionCache(); + + @Import("ObjectDefinition_cachedModelData") + RSEvictingDualNodeHashTable getObjectDefinitionModelDataCache(); + + @Import("ObjectDefinition_cachedEntities") + RSEvictingDualNodeHashTable getObjectDefinitionEntitiesCache(); + + @Import("ParamDefinition_cached") + RSEvictingDualNodeHashTable getParamDefinitionCache(); + + @Import("PlayerAppearance_cachedModels") + RSEvictingDualNodeHashTable getPlayerAppearanceModelsCache(); + + @Import("SequenceDefinition_cached") + RSEvictingDualNodeHashTable getSequenceDefinitionCache(); + + @Import("SequenceDefinition_cachedFrames") + RSEvictingDualNodeHashTable getSequenceDefinitionFramesCache(); + + @Import("SequenceDefinition_cachedModel") + RSEvictingDualNodeHashTable getSequenceDefinitionModelsCache(); + + @Import("SpotAnimationDefinition_cached") + RSEvictingDualNodeHashTable getSpotAnimationDefinitionCache(); + + @Import("SpotAnimationDefinition_cachedModels") + RSEvictingDualNodeHashTable getSpotAnimationDefinitionModlesCache(); + + @Import("VarcInt_cached") + RSEvictingDualNodeHashTable getVarcIntCache(); + + @Import("VarpDefinition_cached") + RSEvictingDualNodeHashTable getVarpDefinitionCache(); + + @Import("Widget_cachedModels") + RSEvictingDualNodeHashTable getModelsCache(); + + @Import("Widget_cachedFonts") + RSEvictingDualNodeHashTable getFontsCache(); + + @Import("Widget_cachedSpriteMasks") + RSEvictingDualNodeHashTable getSpriteMasksCache(); + + @Import("WorldMapElement_cachedSprites") + RSEvictingDualNodeHashTable getSpritesCache(); + + @Construct + RSIterableNodeHashTable createIterableNodeHashTable(int size); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSDualNode.java b/runescape-api/src/main/java/net/runelite/rs/api/RSDualNode.java index 347eac07eb..a2effeddef 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSDualNode.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSDualNode.java @@ -29,6 +29,9 @@ import net.runelite.mapping.Import; public interface RSDualNode extends RSNode, DualNode { + @Import("previousDual") + RSDualNode previousDual(); + @Import("removeDual") void unlinkDual(); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSEvictingDualNodeHashTable.java b/runescape-api/src/main/java/net/runelite/rs/api/RSEvictingDualNodeHashTable.java index 3f59cdaa47..f4bf30fbc3 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSEvictingDualNodeHashTable.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSEvictingDualNodeHashTable.java @@ -8,15 +8,44 @@ public interface RSEvictingDualNodeHashTable extends NodeCache @Import("get") RSDualNode get(long id); + @Import("dualNode") + RSDualNode getDualNode(); + @Import("clear") @Override void reset(); + @Import("capacity") + int getCapacity(); + @Import("capacity") @Override void setCapacity(int capacity); + @Import("remainingCapacity") + int getRemainingCapacity(); + @Import("remainingCapacity") @Override void setRemainingCapacity(int remainingCapacity); + + @Import("deque") + RSIterableDualNodeQueue getDeque(); + + @Import("hashTable") + void setHashTable(RSIterableNodeHashTable hashTable); + + float getThreshold(); + + void setThreshold(float threshold); + + int getTmpCapacity(); + + void setTmpCapacity(int tmpCapacity); + + boolean isTrashing(); + + void resize(int newSize); + + void increaseCapacity(int newSize); } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSIterableDualNodeQueue.java b/runescape-api/src/main/java/net/runelite/rs/api/RSIterableDualNodeQueue.java index 0993820966..d3847f12b0 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSIterableDualNodeQueue.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSIterableDualNodeQueue.java @@ -1,3 +1,9 @@ package net.runelite.rs.api; -public interface RSIterableDualNodeQueue {} +import net.runelite.mapping.Import; + +public interface RSIterableDualNodeQueue +{ + @Import("add") + void add(RSDualNode var1); +} diff --git a/runescape-client/src/main/java/EvictingDualNodeHashTable.java b/runescape-client/src/main/java/EvictingDualNodeHashTable.java index da17922d03..f5e730cdaf 100644 --- a/runescape-client/src/main/java/EvictingDualNodeHashTable.java +++ b/runescape-client/src/main/java/EvictingDualNodeHashTable.java @@ -10,7 +10,8 @@ public final class EvictingDualNodeHashTable { @ObfuscatedSignature( descriptor = "Lnc;" ) - DualNode field2797; + @Export("dualNode") + DualNode dualNode; @ObfuscatedName("b") @Export("capacity") int capacity; @@ -31,7 +32,7 @@ public final class EvictingDualNodeHashTable { IterableDualNodeQueue deque; public EvictingDualNodeHashTable(int var1) { - this.field2797 = new DualNode(); + this.dualNode = new DualNode(); this.deque = new IterableDualNodeQueue(); this.capacity = var1; this.remainingCapacity = var1; @@ -79,7 +80,7 @@ public final class EvictingDualNodeHashTable { DualNode var4 = this.deque.removeLast(); var4.remove(); var4.removeDual(); - if (var4 == this.field2797) { + if (var4 == this.dualNode) { var4 = this.deque.removeLast(); var4.remove(); var4.removeDual(); @@ -97,7 +98,7 @@ public final class EvictingDualNodeHashTable { public void clear() { this.deque.clear(); this.hashTable.clear(); - this.field2797 = new DualNode(); + this.dualNode = new DualNode(); this.remainingCapacity = this.capacity; } }