13 KiB
Item charges – Taskbeschreibung
Implementiere einen „Item charges"-Helper in Essentials Plus (com.example.essentialsplus.helpers): Auf dem Icon jedes Items mit bekanntem Charge/Füllstand wird eine Zahl gerendert. Manche Items zeigen mehrere Zahlen (z. B. Toxic Blowpipe: Scales + Darts). Togglebar per Checkbox, anzeige in Inventar, Ausrüstung und (optional) Bank.
Beispiele:
- Toxic Blowpipe (mit Scales) →
scales-Zahl; mit geladenen Darts → zweiter Wert (Darts-Marker, s. Hinweise). - Dizan's Quiver → zwei Zahlen: Ammo (
CHARGES_DIZANAS_QUIVER_QUANTITY) + Blessing (CHARGES_DIZANAS_QUIVER_BLESSING). - Trident/Shadow/Tome/Bowfa etc. → eine Zahl.
- Lootingsack: Geldwert (Coins) als Zahl auf dem Sack-Icon.
- Coal Bag: Füllstand via Chat-Tracking + Persistenz (kein Varbit!).
Format: Ganzzahlen / Stack-Format (Geld: QuantityFormatter.quantityToStackSize, z. B. 1.2M). Unbekannter Wert → ?.
Datenquellen & Mechanik
1. CHARGES_*-Varbits (Hauptquelle, charakterweit)
Werte via client.getVarbitValue(id) (net.runelite.api.gameval.VarbitID). Mapping Item-Gruppe → Varbit (verifiziert, Release 1.12.39). Varbit aus der ID-Variante des Items ableiten (s. Quelle 2), nicht aus einem Katalog — zwei identische Waffen haben nur EINEN Varbit-Wert (OSRS-Grenze!).
| Item-Gruppe (ItemID-Konstanten) | VarbitID-Konstante |
|---|---|
TOXIC_BLOWPIPE, TOXIC_BLOWPIPE_LOADED, TOXIC_BLOWPIPE_ORNAMENT, TOXIC_BLOWPIPE_LOADED_ORNAMENT |
CHARGES_TOXIC_BLOWPIPE_QUANTITY |
SERPENTINE_HELM, SERPENTINE_HELM_CHARGED, _CYAN, _CYAN_CHARGED, _RED, _RED_CHARGED |
CHARGES_SERPENTINE_HELM_QUANTITY |
WARPED_SCEPTRE, WARPED_SCEPTRE_UNCHARGED |
CHARGES_WARPED_SCEPTRE_QUANTITY |
TUMEKENS_SHADOW, TUMEKENS_SHADOW_UNCHARGED, TUMEKENS_HEKA, TUMEKENS_HEKA_UNCHARGED |
CHARGES_TUMEKENS_SHADOW_QUANTITY |
SANGUINESTI_STAFF, SANGUINESTI_STAFF_UNCHARGED, _OR, _UNCHARGED_OR |
CHARGES_SANGUINESTI_STAFF_QUANTITY |
TRIDENT_OF_THE_SEAS (+ _E), jew. gecharge/un-gecharge-Varianten |
CHARGES_TRIDENT_OF_THE_SEAS_QUANTITY bzw. ..._E_QUANTITY |
TOXIC_STAFF_OF_THE_DEAD (+ _UNCHARGED, _OR-Varianten) |
CHARGES_TOXIC_STAFF_OF_THE_DEAD_QUANTITY |
BOW_OF_FAERDHINEN, BOW_OF_FAERDHINEN_INACTIVE, _INFINITE* |
CHARGES_BOW_OF_FAERDHINEN_QUANTITY (+ CHARGES_BOW_OF_FAERDHINEN_CORRUPTION für korrupte Variante) |
BLADE_OF_SAELDOR, BLADE_OF_SAELDOR_INACTIVE, _INFINITE |
CHARGES_BLADE_OF_SAELDOR_QUANTITY (+ _CORRUPTION) |
VENATOR_BOW, VENATOR_BOW_UNCHARGED, VENATOR_BOW_ORNAMENT(_UNCHARGED) |
CHARGES_VENATOR_BOW_QUANTITY |
TONALZTICS_OF_RALOS_CHARGED, _UNCHARGED |
CHARGES_TONALZTICS_OF_RALOS_QUANTITY |
ARCLIGHT |
CHARGES_ARCLIGHT_QUANTITY |
DIZANAS_QUIVER_CHARGED, _UNCHARGED, _INFINITE, _BROKEN, Trouver-Varianten |
CHARGES_DIZANAS_QUIVER_QUANTITY (Ammo) + CHARGES_DIZANAS_QUIVER_BLESSING (Blessing) — zwei Zahlen |
TOME_OF_FIRE, TOME_OF_FIRE_UNCHARGED |
CHARGES_TOME_OF_FIRE_QUANTITY |
TOME_OF_WATER, TOME_OF_WATER_UNCHARGED |
CHARGES_TOME_OF_WATER_QUANTITY |
TOME_OF_EARTH, TOME_OF_EARTH_UNCHARGED |
CHARGES_TOME_OF_EARTH_QUANTITY |
ASH_SANCTIFIER |
CHARGES_ASH_SANCTIFIER_QUANTITY |
BONECRUSHER |
CHARGES_BONECRUSHER_QUANTITY |
BRYOPHYTAS_STAFF |
CHARGES_BRYOPHYTAS_STAFF_QUANTITY |
CIRCLET_OF_WATER |
CHARGES_CIRCLET_OF_WATER_QUANTITY |
SOUL_BEARER |
CHARGES_SOUL_BEARER_QUANTITY |
CELESTIAL_RING, CELESTIAL_RING_CHARGED |
CHARGES_CELESTIAL_RING_QUANTITY |
WILD_CAVE_SCEPTRE_CHARGED, WILD_CAVE_SCEPTRE_UNCHARGED |
CHARGES_WILDERNESS_WEAPON_QUANTITY |
BRACELET_OF_ETHEREUM |
CHARGES_BRACELET_OF_ETHEREUM_QUANTITY |
RING_OF_SUFFERING |
CHARGES_RING_OF_SUFFERING_QUANTITY |
XERIC_TALISMAN, XERIC_TALISMAN_EMPTY |
CHARGES_XERICS_TALISMAN_QUANTITY |
RING_OF_SHADOWS, RING_OF_SHADOWS_UNCHARGED |
CHARGES_RING_OF_SHADOWS_QUANTITY |
ECHO_BOOTS |
CHARGES_ECHO_BOOTS_QUANTITY |
AMULET_OF_BLOOD_FURY |
CHARGES_AMULET_OF_BLOOD_FURY_QUANTITY |
GIANTSOUL_AMULET_CHARGED, _UNCHARGED |
CHARGES_GIANTSOUL_AMULET_QUANTITY |
EYE_OF_AYAK, EYE_OF_AYAK_UNCHARGED |
CHARGES_EYE_OF_AYAK_QUANTITY |
HORN_OF_PLENTY, _UNCHARGED, SAILORS_AMULET, _EMPTY, COWBELL_AMULET, _EMPTY, PENDANT_OF_ATES, _EMPTY |
jew. CHARGES_*_QUANTITY-Varbit |
Crystal Armour/Tools (Crystal, CRYSTAL_* piece IDs) |
CHARGES_CRYSTAL_ARMOUR_QUANTITY, CHARGES_CRYSTAL_TOOLS_QUANTITY, CHARGES_CRYSTAL_WEAK_QUANTITY |
ALCHEMIST_RING |
CHARGES_ALCHEMIST_AMULET_QUANTITY |
Vollständige Liste ergänzen per javap -constants net.runelite.api.gameval.VarbitID | grep 'CHARGES_.*_QUANTITY' gegen das runelite-api-Jar (release 1.12.39; Pfad s. Referenzen). Das sind ~55 Konstanten; es kommen auch Solo-/Sailing-Charges vor (CHARGES_PLANK_SACK*, CHARGES_BOWSTRING_SPOOL*), nur relevante übernehmen. Stichproben-Hinweis: DBTableID$Charges$Row (in runelite-api net.runelite.api.gameval.DBTableID) listet dieselben Charge-Typen als DB-Rows (Referenz/Querschnitt, nicht zwingend zur Laufzeit nötig).
Varianten-Ableitung für die Tabelle: Einträge in net.runelite.api.gameval.ItemID mit typischen Suffixen (_CHARGED, _UNCHARGED, _INACTIVE, _EMPTY, _LOADED, _OR, _CYAN/_RED, _TROUVER, _INFINITE, _BROKEN) — per javap -constants ... ItemID | grep verifizieren.
2. Item-ID-Statusvarianten (Ladungs-Status)
Viele Items wechseln die Item-ID bei leer/laden — mehrere exakte IDs auf dieselbe Charge abbilden bzw. „0"-Semantik:
TOXIC_BLOWPIPE(12924) vsTOXIC_BLOWPIPE_LOADED(12926): Darts geladen: ja/nein (zweiter Wert, Marker; die exakte Dart-Anzahl ist NICHT in der API — kein Varbit/Container).DRYGORE_BLOWPIPEvsDRYGORE_BLOWPIPE_LOADEDanalog.BOW_OF_FAERDHINEN_INACTIVE→ 0;BLADE_OF_SAELDOR_INACTIVE→ 0;*_INFINITE→ „∞".- Alle
*_UNCHARGED/*_EMPTY→ 0 bzw. kein Varbit abfragen.
3. Container (Echtzeit; per GameTick gelesen)
- Lootingsack:
client.getItemContainer(InventoryID.LOOTING_BAG)(auchLOOTING_BAG_OPEN). Geldwert = Σ qty vonItemID.COINSim Container. (Plugin hat bereitsreadContainer()/WealthStore für Loot — hier eigenes Lesen im Overlay-Tick, da das Overlay nicht an den Container-Event gebunden ist.) - Dizan's Quiver Ammo:
InventoryID.DIZANAS_QUIVER_AMMOals Crosscheck/Geld-Anzeige zum Varbit-Wert möglich. - Coal/Gem/Herb sack: kein Container, kein Varbit (verifiziert) → Quelle 4.
4. Coal Bag — Chat-Tracking + Persistenz
- Kein Varbit/Container in
VarbitID/InventoryID(verifiziert; nurItemID.COAL_BAG/COAL_BAG_OPEN). - Füllstand (max 27) ableiten aus Chat-Nachrichten + letzten bekannten Wert pro Account in
configManagerpersistieren (keycoalBag.<accountKey>, Wert int 0–27;accountKey-Konvention wie bestehende Persistenz im Plugin). - Zu verarbeitende Muster (ChatMessage-Filter
Game): Check-/Fill-Feedback „[…]Xcoal in your coal bag]" o. Ä. exakt in-game verifizieren (2024 wurde Feedback von Popups auf Chat umgestellt); zusätzlich Empty → 0; bei unbekannter Nachricht/Login ohne Check →?anzeigen statt falscher Zahl. ChatMessage-Events: Fehler-tolerant parsen (Regex), bei Update sofort speichern. BeimLOGOUTaktuellen Wert speichern. Optional Rechtsklick „Coal bag vergessen" → Wert nicht aus Chat-Nachrichten ableiten.
Neue Dateien
helpers/ItemCharges.java (@Singleton, Logik)
- Datenmodell:
ChargeValue { String text; Color color; }(+ optional 2. Wert). Lookup-APIList<ChargeValue> chargesFor(int itemId):- exakte
itemIdin Tabelle (Load/Empty/Inactive-Varianten); dann itemManager.canonicalize(itemId)(Noten/Placeholder) erneut prüfen.
- exakte
CHARGE_MAP:Map<Integer itemId, ChargeSource>statisch aufgebaut aus den ItemID-Konstanten (Quelle 1+2);ChargeSource= Varbit-Konstante bzw.COAL_BAG-Typ bzw.LOOTING_BAG-Container-Typ.- State: Coal-Bag-Count pro Account +
Map<Integer, ...>-Cache nur so weit nötig (Varbit-Lesen ist billig; kein harter Cache zwingend). - Events (im Plugin registriert, Muster
TreeCooldowns):GameTick→ die zwei Bag-Varbits/Container aktualisieren.VarbitChanged→ relevante Varbit-Id → Value merken.ChatMessage→ Coal-Bag-Messages parsen (s. o.), speichern.GameStateChanged→!= LOGGED_IN→reset(), Coal-Bag-Count ausconfigManagerladen bzw. auf „?" zurücksetzen.
- Reset: Coal-Bag-Cache auf
?beim Logout (Persistenz bleibt).
helpers/ItemChargesOverlay.java (WidgetItemOverlay)
showOnInventory(); showOnEquipment(); showOnBank();— Bank über Config-Sub-Key steuerbar (s. unten).renderItemOverlay(g, itemId, WidgetItem):if (!config.itemCharges()) return;List<ChargeValue>auschargesFor(itemId); leer → nichts rendern.- Zahl unten-links am Icon (offizielles RuneLite-Muster):
bounds.x - 1, bounds.y + 15, mit Schatten (Fonts.RUNESCAPE_SMALLbzw.TimerTextSize), Farbe ausitemChargesColor; 2. Wert (Blowpipe-Darts, Quiver-Blessing) darüber (bounds.y - 3) initemChargesSecondaryColor. - Geld (Lootingsack): Stack-Size-Format; Low-Charge-Färbung ab
itemChargesLowAt→itemChargesLowColor.
- Coins/Loot-Bag-Wert: aus
chargesFor(LOOTING_BAG_OPEN/LOOTING_BAG)-Container-Lesung im Overlay-Tick (Falls Container null → kein Wert).
Zu ändernde Dateien
EssentialsPlusConfig.java:@ConfigItem itemCharges(bool, defaultfalse, position ~37). Optionen alsconfigManager-Keys viasetHelperOption(Muster wie treeCooldowns):itemChargesWeapons(bool, true) — Varbit-Charges an/ausitemChargesBags(bool, true) — Loot-Bag-Geld + Coal-Bag-Füllstand an/ausitemChargesBank(bool, false) — Overlay auch in Bank (Achtung Hinweise!)itemChargesSize(TimerTextSize, SMALL),itemChargesColor(Color, weiß),itemChargesSecondaryColor(Color, hellgrau0xC0C0C0),itemChargesLowColor(Color, rot0xFF3333),itemChargesLowAt(int, 0 = aus)
EssentialsPlusPlugin.java:@Inject ItemCharges+ItemChargesOverlay;startUp():eventBus.register(itemCharges),overlayManager.add(itemChargesOverlay);shutDown(): spiegeln +itemCharges.reset().isHelperOption():case "itemCharges"→config.itemCharges().setHelperOption/onConfigChanged: Bestände füritemcharges*-Keys refresh (Muster solcher Bestands-Abschnitte).HelpersCard.java: neuesJCheckBox "Item charges"(Tooltip: „Charge-Zahl auf Item-Icons (Blowpipe, Trident, Tome, …) + Loot-Bag-Geld & Coal-Bag-Füllstand. Rechtsklick für Optionen"). Rechtsklick-Menü analogstyleMenu/treeMenu: TogglesitemChargesWeapons/itemChargesBags/itemChargesBank, Größe, Farben, Schwellenwert, Reset.refresh()erweitern.
Verifikation
./gradlew compileJava(bzw../gradlew deployfür Bolt).- Manuell: Blowpipe mit Scales (nur Scales-Zahl) → mit Darts laden (2. Zahl erscheint); Trident/Shadow/Sang/Tome (Zahl); Lootingsack mit Coins betreten (Geld auf Sack-Icon); Coal Bag füllen → Zahl steigt, Empty → 0, Relog → Wert bleibt; Bank öffnen mit
itemChargesBank→ Zahlen auch dort; beide Blowpipes (leer + geladen) im Inventar → korrekte per-ID-Darstellung.
Hinweise / Einschränkungen
CHARGES_*-Varbits sind charakterweit, nicht pro Item-Exemplar: zwei unterschiedlich geladene Tridents zeigen denselben Wert (OSRS-Systemgrenze, deckungsgleich mit dem In-Game-Charge-Overlay).- Bank-Anzeige dementsprechend unzuverlässig für „unbenutzte" Kopien; default daher
itemChargesBank = false. - Coal Bag: nur Heuristik (Chat + Persistenz), kein API-Wert; nach Login unbekannt →
?. - Blowpipe: Dart-Anzahl nicht in der API → 2. Wert ist Darts-geladen-Marker, keine Zahl.
- Keine Chat-Popup-abhängigkeit (Popup = ist abgeschaltet hat), ausschließlich ChatMessage-Events verwenden.
Referenzen
tree-cooldown.md(gleiche Struktur),reflect.txt/Cachierte Jars für Konstanten:- runelite-api:
/home/hikyu/.gradle/caches/modules-2/files-2.1/net.runelite/runelite-api/1.12.39/<hash>/runelite-api-1.12.39.jar→net/runelite/api/gameval/{VarbitID,ItemID,InventoryID,DBTableID$Charges$Row} - client:
/home/hikyu/.gradle/caches/modules-2/files-2.1/net.runelite/client/1.12.39/<hash>/client-1.12.39.jar→net.runelite.client.ui.overlay.WidgetItemOverlay,components.TextComponent,ui.FontManager
- runelite-api:
- Konventionen:
helpers/TreeCooldowns.java(Logik+Events),helpers/TreeCooldownOverlay.java/ItemPriceOverlay.java(Overlay-Zeichnung),HelpersCard.java(Checkbox+Menü),EssentialsPlusPlugin.isHelperOption/setHelperOption/onConfigChanged.