Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion Core/MultiBotComm.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2399,6 +2399,27 @@ function Comm.HandleAddonMessage(prefix, message, distribution, sender)
return true
end

if opcode == "GBANK_RIGHTS" then
local botName, rest = splitOnce(payload or "", "~")
local token, rest2 = splitOnce(rest or "", "~")
local canWithdraw, remaining = splitOnce(rest2 or "", "~")
botName = trim(urlDecodeField(botName))
canWithdraw = trim(canWithdraw)
remaining = tonumber(remaining or "0") or 0
state.connected = true
state.lastError = nil

local active = getActiveGuildBankRequest(botName, token)
if active then
active.rights = {
canWithdraw = canWithdraw == "1" or string.lower(canWithdraw) == "true",
remaining = remaining,
}
end

return true
end

if opcode == "GBANK_END" then
local botName, token = splitOnce(payload or "", "~")
botName = trim(urlDecodeField(botName))
Expand All @@ -2410,7 +2431,7 @@ function Comm.HandleAddonMessage(prefix, message, distribution, sender)
local key = string.lower(botName)
state.guildBankItems[key] = active.items or {}
if MultiBot.OnBridgeGuildBankItems then
MultiBot.OnBridgeGuildBankItems(botName, state.guildBankItems[key], active.error, token)
MultiBot.OnBridgeGuildBankItems(botName, state.guildBankItems[key], active.error, token, active.rights)
end
end

Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ GET~OUTFITS
GET~QUESTS
GET~GAMEOBJECTS
RUN~CRAFT_RECIPE
RUN~ITEM_ACTION
RUN~OUTFIT
RUN~RTI
RUN~COMBAT
Expand Down Expand Up @@ -175,7 +176,7 @@ The goal is to remove automatic UI-refresh spam.
</tr>
<tr>
<td>Bot bank / guild bank / vendor buy</td>
<td><strong>Bridge-first</strong> bank snapshots, guild bank snapshots, bank deposit/withdraw, guild bank deposit and vendor buy actions</td>
<td><strong>Bridge-first</strong> bank snapshots, guild bank snapshots, bank deposit/withdraw, guild bank deposit/withdraw and vendor buy actions</td>
</tr>
<tr>
<td>Profession recipe frame</td>
Expand Down Expand Up @@ -470,7 +471,7 @@ Implemented bridge-first / chatless areas:
- Inventory refresh with icons and item tooltips.
- Spellbook refresh, with profession/crafting spells separated from the combat spellbook path.
- Character Info frame through the bridge with Blizzard-style tabs for class, profession, secondary, weapon and armor skills, reputations and currencies/emblems.
- Bot bank and guild bank snapshots through the bridge, plus bank deposit/withdraw, guild bank deposit and vendor buy item actions.
- Bot bank and guild bank snapshots through the bridge, plus bank deposit/withdraw, guild bank deposit/withdraw and vendor buy item actions.
- Profession recipe frame through the bridge, opened from profession and secondary skill rows.
- Glyph refresh with icons and glyph tooltips.
- Outfits refresh and actions through the bridge.
Expand Down
8 changes: 2 additions & 6 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
## Informations bot
* Dans les frames métier ajout d'un bouton pour faire le bot acheter les composants manquants pour crafter l'item.
* Infos personnage : onglets style Blizzard pour compétences, réputations et monnaies.
* Ajouter un bouton pour abandonner les quêtes dans la frame de quêtes finies et en cours des bots
* Ajouter un bouton pour retirer des objets de la banque de guilde


## Inventaire Bot étendu
Expand All @@ -32,9 +30,6 @@
* Ajout d'une frame pour afficher le contenu de la banque de guilde.

** TODO
* Voire si on tient compte des droits de guilde pour les retraits et dépôts, et si les rangs des bots évoluent dans playerbots.
* Uniformiser le layout des frames de banque bot et BDG
* Ajouter un bouton retrait à la frame BDG
* Afficher les sous de la guilde dans la frame BDG

## Frame Loot
Expand Down Expand Up @@ -112,7 +107,8 @@
* Réputations bridge-first dans la frame Infos personnage.
* Monnaies / emblèmes bridge-first dans la frame Infos personnage, avec argent du bot.
* Banque bot bridge-first avec consultation, dépôt et retrait.
* Banque de guilde bot bridge-first avec consultation et dépôt.
* Banque de guilde bot bridge-first avec consultation, dépôt et retrait protégé par les droits de guilde.
* Layout des frames banque bot et BDG uniformisé avec fond interne sombre.
* Achat vendeur bridge-first depuis les composants manquants de recette métier.
* Profession recipes bridge-first.
* Craft de recettes métier via bridge `RUN~CRAFT_RECIPE`.
Expand Down
85 changes: 74 additions & 11 deletions UI/MultiBotBankFrame.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ local BANK_FRAME_X = -360
local BANK_ROW_WIDTH = 300
local BANK_TEXT_WIDTH = 210
local BANK_WITHDRAW_BUTTON_WIDTH = 70
local BANK_WITHDRAW_BUTTON_OFFSET_X = -8
local BANK_REFRESH_DELAY = 0.65

local function L(key, fallback)
Expand All @@ -34,6 +35,29 @@ local function setButtonEnabled(button, enabled)
end
end

local function addSimpleBackdrop(frame, bgAlpha)
if not frame or not frame.SetBackdrop then
return
end

frame:SetBackdrop({
bgFile = "Interface\\Buttons\\WHITE8x8",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true,
tileSize = 16,
edgeSize = 14,
insets = { left = 3, right = 3, top = 3, bottom = 3 },
})

if frame.SetBackdropColor then
frame:SetBackdropColor(0.06, 0.06, 0.08, bgAlpha or 0.90)
end

if frame.SetBackdropBorderColor then
frame:SetBackdropBorderColor(0.35, 0.35, 0.35, 0.95)
end
end

local function createWindow(name, title, width, height, pointX)
if AceGUI then
local widget = AceGUI:Create("Window")
Expand All @@ -44,6 +68,11 @@ local function createWindow(name, title, width, height, pointX)
widget.frame:SetPoint("CENTER", UIParent, "CENTER", pointX or 0, 0)
widget.frame:SetFrameStrata("DIALOG")
widget:EnableResize(false)

if widget.content then
addSimpleBackdrop(widget.content, 0.90)
end

return widget
end

Expand All @@ -54,9 +83,15 @@ local function createWindow(name, title, width, height, pointX)
frame.title = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
frame.title:SetPoint("TOP", 0, -7)
frame.title:SetText(title)

frame.content = CreateFrame("Frame", nil, frame)
frame.content:SetPoint("TOPLEFT", frame, "TOPLEFT", 10, -30)
frame.content:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -10, 10)
addSimpleBackdrop(frame.content, 0.90)

return {
frame = frame,
content = frame,
content = frame.content,
SetTitle = function(self, value) self.frame.title:SetText(value) end,
Show = function(self) self.frame:Show() end,
Hide = function(self) self.frame:Hide() end,
Expand Down Expand Up @@ -172,8 +207,24 @@ local function getBankModeBridgeRequiredText(mode)
return L("inventory.bank.bridge.required", "Bank bridge is not connected.")
end

local function canWithdrawFromMode(mode)
return mode ~= "gbank"
local function getWithdrawActionForMode(mode)
if mode == "gbank" then
return "GBANK_WITHDRAW"
end

return "BANK_WITHDRAW"
end

local function canWithdrawFromFrame(frame)
if not frame then
return false
end

if frame.mode == "gbank" then
return frame.gbankCanWithdraw == true
end

return true
end

local function ensureBankFrame()
Expand Down Expand Up @@ -209,18 +260,24 @@ local function ensureBankFrame()
row.text:SetHeight(22)

row.withdrawButton = CreateFrame("Button", nil, row, "UIPanelButtonTemplate")
row.withdrawButton:SetPoint("RIGHT", row, "RIGHT", 0, 0)
row.withdrawButton:SetPoint("RIGHT", row, "RIGHT", BANK_WITHDRAW_BUTTON_OFFSET_X, 0)
row.withdrawButton:SetWidth(BANK_WITHDRAW_BUTTON_WIDTH)
row.withdrawButton:SetHeight(20)
row.withdrawButton:SetText(L("inventory.bank.withdraw", "Withdraw"))
row.withdrawButton:SetScript("OnClick", function()
local item = row.item
if not item or not frame.botName or not canWithdrawFromMode(frame.mode) then
local action = getWithdrawActionForMode(frame.mode)
if not item or not frame.botName or not action then
return
end

if not canWithdrawFromFrame(frame) then
frame.status:SetText(getBankReasonText("NO_GUILD_BANK_RIGHTS"))
return
end

if MultiBot.Comm and MultiBot.Comm.RunInventoryItemAction then
local token = MultiBot.Comm.RunInventoryItemAction(frame.botName, "BANK_WITHDRAW", item.itemId, 0)
local token = MultiBot.Comm.RunInventoryItemAction(frame.botName, action, item.itemId, 0)
if token then
frame.status:SetText(L("inventory.bank.withdraw.pending", "Withdraw requested..."))
setButtonEnabled(row.withdrawButton, false)
Expand Down Expand Up @@ -279,9 +336,9 @@ local function ensureBankFrame()
if item then
row.icon:SetTexture(MultiBot.SafeTexturePath(item.icon))
row.text:SetText((item.name or ("item:" .. item.itemId)) .. " |cff999999x" .. tostring(item.count or 1) .. "|r")
if canWithdrawFromMode(self.mode) then
if getWithdrawActionForMode(self.mode) then
row.withdrawButton:SetText(L("inventory.bank.withdraw", "Withdraw"))
setButtonEnabled(row.withdrawButton, true)
setButtonEnabled(row.withdrawButton, canWithdrawFromFrame(self))
row.withdrawButton:Show()
else
row.withdrawButton:Hide()
Expand All @@ -304,9 +361,11 @@ local function ensureBankFrame()
frame:render()
end)

frame.setItems = function(self, botName, lines, errorReason, mode)
frame.setItems = function(self, botName, lines, errorReason, mode, guildBankRights)
self.botName = botName
self.mode = mode or self.mode or "bank"
self.gbankCanWithdraw = self.mode == "gbank" and type(guildBankRights) == "table" and guildBankRights.canWithdraw == true
self.gbankWithdrawRemaining = self.mode == "gbank" and type(guildBankRights) == "table" and tonumber(guildBankRights.remaining or 0) or 0
self.items = {}
self.page = 1
setWindowTitle(self, getBankModeTitle(self.mode) .. " - " .. tostring(botName or ""))
Expand Down Expand Up @@ -341,6 +400,8 @@ function MultiBot.OpenBotBank(botName)
local frame = ensureBankFrame()
frame.botName = botName
frame.mode = "bank"
frame.gbankCanWithdraw = false
frame.gbankWithdrawRemaining = 0
frame.items = {}
frame.page = 1
setWindowTitle(frame, getBankModeTitle(frame.mode) .. " - " .. botName)
Expand All @@ -365,6 +426,8 @@ function MultiBot.OpenBotGuildBank(botName)
local frame = ensureBankFrame()
frame.botName = botName
frame.mode = "gbank"
frame.gbankCanWithdraw = false
frame.gbankWithdrawRemaining = 0
frame.items = {}
frame.page = 1
setWindowTitle(frame, getBankModeTitle(frame.mode) .. " - " .. botName)
Expand Down Expand Up @@ -428,8 +491,8 @@ function MultiBot.OnBridgeBankItems(botName, lines, errorReason)
ensureBankFrame():setItems(botName, lines or {}, errorReason, "bank")
end

function MultiBot.OnBridgeGuildBankItems(botName, lines, errorReason)
ensureBankFrame():setItems(botName, lines or {}, errorReason, "gbank")
function MultiBot.OnBridgeGuildBankItems(botName, lines, errorReason, token, guildBankRights)
ensureBankFrame():setItems(botName, lines or {}, errorReason, "gbank", guildBankRights)
end

function MultiBot.InitializeBankFrame()
Expand Down
13 changes: 12 additions & 1 deletion UI/MultiBotInventoryItem.lua
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ function MultiBot.OnBridgeInventoryItemActionResult(botName, action, itemId, res
if MultiBot.RefreshBotBank and (action == "BANK_DEPOSIT" or action == "BANK_WITHDRAW") then
MultiBot.RefreshBotBank(botName, 0.65)
end
if action == "GBANK_DEPOSIT" and MultiBot.RefreshBotGuildBank then
if (action == "GBANK_DEPOSIT" or action == "GBANK_WITHDRAW") and MultiBot.RefreshBotGuildBank then
MultiBot.RefreshBotGuildBank(botName, 0.65)
end
if action == "BUY_ITEM" and MultiBot.professionRecipeFrame and MultiBot.professionRecipeFrame:IsShown()
Expand All @@ -573,6 +573,17 @@ function MultiBot.OnBridgeInventoryItemActionResult(botName, action, itemId, res
end

local reasonText = getInventoryItemActionReason(reason)
if (action == "BANK_WITHDRAW" or action == "GBANK_WITHDRAW")
and MultiBot.bankFrame and MultiBot.bankFrame.IsShown and MultiBot.bankFrame:IsShown()
and MultiBot.bankFrame.botName == botName then
if MultiBot.bankFrame.status then
MultiBot.bankFrame.status:SetText(reasonText ~= "" and reasonText or tostring(reason or ""))
end
if MultiBot.bankFrame.render then
MultiBot.bankFrame:render()
end
end

if action == "BUY_ITEM" and MultiBot.professionRecipeFrame and MultiBot.professionRecipeFrame:IsShown()
and MultiBot.professionRecipeFrame.botName == botName
and MultiBot.professionRecipeFrame.status then
Expand Down
10 changes: 5 additions & 5 deletions docs/multibot_bridge_chatless_roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ Le but n’est pas de supprimer ces commandes. Le but est de ne plus les lancer
- [x] Endpoint côté bridge : `GET~BANK~<bot>~<token>`
- [x] Réponses en paquets courts : `BANK_BEGIN`, `BANK_ITEM`, `BANK_ERROR`, `BANK_END`
- [x] Endpoint côté bridge : `GET~GBANK~<bot>~<token>`
- [x] Réponses en paquets courts : `GBANK_BEGIN`, `GBANK_ITEM`, `GBANK_ERROR`, `GBANK_END`
- [x] Réponses en paquets courts : `GBANK_BEGIN`, `GBANK_RIGHTS`, `GBANK_ITEM`, `GBANK_ERROR`, `GBANK_END`
- [x] Endpoint côté bridge : `RUN~ITEM_ACTION~<bot>~<token>~<action>~<itemId>~<count>`
- [x] Actions validées : dépôt banque bot, retrait banque bot, dépôt banque de guilde et achat vendeur
- [x] Actions validées : dépôt banque bot, retrait banque bot, dépôt banque de guilde, retrait banque de guilde et achat vendeur
- [x] Consultation BDG basée sur la guilde du bot, sans exiger que le joueur soit dans la même guilde
- [x] Détection des banquiers neutres avec flags compatibles Dalaran
- [x] Messages d'erreur structurés pour banquier introuvable, droits BDG, vendeur introuvable, objet non vendu et monnaie spéciale
Expand Down Expand Up @@ -283,7 +283,7 @@ Avec beaucoup de bots, éviter les réponses globales trop grosses.
- `GET~BOT_EMBLEMS` répond en paquets `BOT_EMBLEMS_BEGIN` / `BOT_EMBLEM_ITEM` / `BOT_EMBLEMS_MONEY` / `BOT_EMBLEMS_END` ;
- `GET~PROFESSION_RECIPES` répond en paquets `PROFESSION_RECIPES_BEGIN` / `PROFESSION_RECIPES_ITEM` / `PROFESSION_RECIPES_END` ;
- `GET~BANK` répond en paquets `BANK_BEGIN` / `BANK_ITEM` / `BANK_ERROR` / `BANK_END` ;
- `GET~GBANK` répond en paquets `GBANK_BEGIN` / `GBANK_ITEM` / `GBANK_ERROR` / `GBANK_END` ;
- `GET~GBANK` répond en paquets `GBANK_BEGIN` / `GBANK_RIGHTS` / `GBANK_ITEM` / `GBANK_ERROR` / `GBANK_END` ;
- un paquet global vide peut seulement servir de réponse vide si aucun bot n’est disponible.

---
Expand Down Expand Up @@ -330,7 +330,7 @@ Le craft de recette passe par `RUN~CRAFT_RECIPE`. Les recettes à résultat alé

Les extensions inventaire banque, banque de guilde et achat vendeur sont maintenant bridge-first pour les chemins validés. La banque du bot et la banque de guilde du bot peuvent être consultées via `GET~BANK` et `GET~GBANK`.

Les actions dépôt banque, retrait banque, dépôt banque de guilde et achat vendeur passent par `RUN~ITEM_ACTION`. Le retrait banque de guilde reste à traiter séparément si l'UI doit l'exposer plus tard, car il demande des garde-fous supplémentaires côté droits et logs.
Les actions dépôt banque, retrait banque, dépôt banque de guilde, retrait banque de guilde et achat vendeur passent par `RUN~ITEM_ACTION`. Le retrait BDG est exposé dans l'UI avec un bouton grisé quand le bot n'a plus de droits de retrait disponibles.

### Audit chatless final

Expand Down Expand Up @@ -435,7 +435,7 @@ Le prochain pas logique est maintenant : **audit résiduel + Roll / ventes / ope
5. tester un craft cuisine sans feu puis avec feu, et vérifier l'erreur localisée ;
6. vérifier en console qu’il n’y a plus de refresh automatique legacy `stats`, `items`, `spells`, `glyphs`, `talents spec list`, `outfit ?` avec `MultiBot.allowLegacyChatFallback = false` ;
7. vérifier que les commandes manuelles volontaires restent fonctionnelles : `who`, `co ?`, `nc ?`, `ss ?`, `.playerbot bot add`, `.playerbot bot remove`, actions inventory, `glyph equip`, sélection de spec et actions Outfits ;
8. poursuivre ensuite avec Roll, ventes existantes, open items bridge-first, retrait BDG et enchantements d'objets si besoin.
8. poursuivre ensuite avec Roll, ventes existantes, open items bridge-first et enchantements d'objets si besoin.

Après cette stabilisation, il restera surtout un audit de nettoyage : supprimer les debug temporaires, garder les fallbacks legacy uniquement quand ils sont utiles au diagnostic, et retirer les parsers historiques devenus morts.

Expand Down
Loading
Loading