Add one-shot item API foundation cleanup
This commit is contained in:
@@ -0,0 +1,428 @@
|
||||
name: One-shot Item API Foundation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [classicapi-enhanced]
|
||||
paths:
|
||||
- '.github/workflows/item-api-foundation.yml'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
patch:
|
||||
if: github.actor != 'github-actions[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout ShaguTweaks
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: classicapi-enhanced
|
||||
|
||||
- name: Centralize ClassicAPI item helpers
|
||||
shell: python
|
||||
run: |
|
||||
from pathlib import Path
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# api.lua: add a small, reusable item compatibility layer.
|
||||
# ------------------------------------------------------------------
|
||||
api = Path('api.lua')
|
||||
text = api.read_text(encoding='utf-8')
|
||||
|
||||
old = '''API.inventory = type(_G.C_Container) == "table"
|
||||
and type(_G.C_Container.GetContainerNumFreeSlots) == "function"
|
||||
|
||||
API.merchant = type(_G.C_MerchantFrame) == "table"
|
||||
'''
|
||||
new = '''API.inventory = type(_G.C_Container) == "table"
|
||||
and type(_G.C_Container.GetContainerNumFreeSlots) == "function"
|
||||
|
||||
API.containeritems = type(_G.C_Container) == "table"
|
||||
and type(_G.C_Container.GetContainerItemID) == "function"
|
||||
|
||||
API.items = type(_G.C_Item) == "table"
|
||||
API.iteminfo = API.items and type(_G.C_Item.GetItemInfo) == "function"
|
||||
API.itemname = API.items and type(_G.C_Item.GetItemNameByID) == "function"
|
||||
API.itemquality = API.items and type(_G.C_Item.GetItemQualityByID) == "function"
|
||||
API.itemprice = API.items and type(_G.C_Item.GetItemSellPriceByID) == "function"
|
||||
|
||||
API.merchant = type(_G.C_MerchantFrame) == "table"
|
||||
'''
|
||||
if old not in text:
|
||||
raise SystemExit('api.lua capability marker not found')
|
||||
text = text.replace(old, new, 1)
|
||||
|
||||
old = '''API.GetContainerNumFreeSlots = function(bag)
|
||||
if API.inventory then
|
||||
return _G.C_Container.GetContainerNumFreeSlots(bag)
|
||||
end
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
API.GetNumJunkItems = function()
|
||||
'''
|
||||
new = '''API.GetContainerNumFreeSlots = function(bag)
|
||||
if API.inventory then
|
||||
return _G.C_Container.GetContainerNumFreeSlots(bag)
|
||||
end
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
-- Item helpers use direct ClassicAPI IDs whenever possible. Legacy links remain
|
||||
-- as a fallback for compatibility with a stock 1.12-style call path.
|
||||
local function GetItemIDFromLink(link)
|
||||
if not link then return end
|
||||
local _, _, itemID = string.find(link, "item:(%d+)")
|
||||
return itemID and tonumber(itemID) or nil
|
||||
end
|
||||
|
||||
API.GetItemIDFromLink = GetItemIDFromLink
|
||||
|
||||
API.GetContainerItemID = function(bag, slot)
|
||||
if API.containeritems then
|
||||
local itemID = _G.C_Container.GetContainerItemID(bag, slot)
|
||||
if itemID then return itemID end
|
||||
end
|
||||
|
||||
return GetItemIDFromLink(_G.GetContainerItemLink(bag, slot))
|
||||
end
|
||||
|
||||
API.GetInventoryItemID = function(unit, slot)
|
||||
if type(_G.GetInventoryItemID) == "function" then
|
||||
local itemID = _G.GetInventoryItemID(unit, slot)
|
||||
if itemID then return itemID end
|
||||
end
|
||||
|
||||
return GetItemIDFromLink(_G.GetInventoryItemLink(unit, slot))
|
||||
end
|
||||
|
||||
API.GetItemInfo = function(item)
|
||||
if API.iteminfo then
|
||||
return _G.C_Item.GetItemInfo(item)
|
||||
end
|
||||
return _G.GetItemInfo(item)
|
||||
end
|
||||
|
||||
API.GetItemNameByID = function(itemID)
|
||||
if not itemID then return end
|
||||
if API.itemname then
|
||||
return _G.C_Item.GetItemNameByID(itemID)
|
||||
end
|
||||
local name = _G.GetItemInfo(itemID)
|
||||
return name
|
||||
end
|
||||
|
||||
API.GetItemQualityByID = function(itemID)
|
||||
if not itemID then return end
|
||||
if API.itemquality then
|
||||
return _G.C_Item.GetItemQualityByID(itemID)
|
||||
end
|
||||
local _, _, quality = _G.GetItemInfo(itemID)
|
||||
return quality
|
||||
end
|
||||
|
||||
API.GetItemSellPriceByID = function(itemID)
|
||||
if not itemID then return end
|
||||
if API.itemprice then
|
||||
return _G.C_Item.GetItemSellPriceByID(itemID)
|
||||
end
|
||||
end
|
||||
|
||||
API.GetNumJunkItems = function()
|
||||
'''
|
||||
if old not in text:
|
||||
raise SystemExit('api.lua function marker not found')
|
||||
text = text.replace(old, new, 1)
|
||||
api.write_text(text, encoding='utf-8', newline='\n')
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# helpers.lua: make common item helpers custom-item aware without
|
||||
# changing their old public semantics.
|
||||
# ------------------------------------------------------------------
|
||||
helpers = Path('helpers.lua')
|
||||
text = helpers.read_text(encoding='utf-8')
|
||||
marker = 'ShaguTweaks.GetItemIDFromLink = function(itemLink)\n'
|
||||
head, sep, _ = text.partition(marker)
|
||||
if not sep:
|
||||
raise SystemExit('helpers.lua item-helper marker not found')
|
||||
|
||||
tail = r'''local function LegacyItemIDFromLink(itemLink)
|
||||
if not itemLink then return end
|
||||
local _, _, itemID = string.find(itemLink, "item:(%d+)")
|
||||
return itemID and tonumber(itemID) or nil
|
||||
end
|
||||
|
||||
ShaguTweaks.GetItemIDFromLink = function(itemLink)
|
||||
local API = ShaguTweaks.API
|
||||
if API and API.GetItemIDFromLink then
|
||||
return API.GetItemIDFromLink(itemLink)
|
||||
end
|
||||
return LegacyItemIDFromLink(itemLink)
|
||||
end
|
||||
|
||||
ShaguTweaks.GetItemCount = function(itemName)
|
||||
if not itemName then return 0 end
|
||||
|
||||
local API = ShaguTweaks.API
|
||||
local count = 0
|
||||
for bag = 4, 0, -1 do
|
||||
for slot = 1, GetContainerNumSlots(bag) do
|
||||
local _, itemCount = GetContainerItemInfo(bag, slot)
|
||||
if itemCount then
|
||||
local itemID
|
||||
if API and API.GetContainerItemID then
|
||||
itemID = API.GetContainerItemID(bag, slot)
|
||||
else
|
||||
itemID = LegacyItemIDFromLink(GetContainerItemLink(bag, slot))
|
||||
end
|
||||
|
||||
local queryName
|
||||
if itemID and API and API.GetItemNameByID then
|
||||
queryName = API.GetItemNameByID(itemID)
|
||||
elseif itemID then
|
||||
queryName = GetItemInfo(itemID)
|
||||
end
|
||||
|
||||
if queryName == itemName then
|
||||
count = count + itemCount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
local itemLinkByNameCache = {}
|
||||
|
||||
local function CacheItemLink(name, link)
|
||||
if name and name ~= "" and link then
|
||||
itemLinkByNameCache[name] = link
|
||||
end
|
||||
return link
|
||||
end
|
||||
|
||||
local function FindOwnedItemLinkByName(name)
|
||||
local API = ShaguTweaks.API
|
||||
|
||||
-- Bags first: this is both much cheaper than an ID sweep and works for Turtle
|
||||
-- custom items whose IDs are far beyond vanilla's original range.
|
||||
for bag = 0, 4 do
|
||||
for slot = 1, GetContainerNumSlots(bag) do
|
||||
local link = GetContainerItemLink(bag, slot)
|
||||
if link then
|
||||
local itemID = API and API.GetContainerItemID and API.GetContainerItemID(bag, slot)
|
||||
or LegacyItemIDFromLink(link)
|
||||
local itemName = itemID and API and API.GetItemNameByID and API.GetItemNameByID(itemID)
|
||||
if not itemName then
|
||||
local _, _, linkedName = string.find(link, "%[(.-)%]")
|
||||
itemName = linkedName
|
||||
end
|
||||
if itemName == name then return link end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Equipped items are another cheap source of already-resolved links.
|
||||
for slot = 0, 19 do
|
||||
local link = GetInventoryItemLink("player", slot)
|
||||
if link then
|
||||
local itemID = API and API.GetInventoryItemID and API.GetInventoryItemID("player", slot)
|
||||
or LegacyItemIDFromLink(link)
|
||||
local itemName = itemID and API and API.GetItemNameByID and API.GetItemNameByID(itemID)
|
||||
if not itemName then
|
||||
local _, _, linkedName = string.find(link, "%[(.-)%]")
|
||||
itemName = linkedName
|
||||
end
|
||||
if itemName == name then return link end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ShaguTweaks.GetItemLinkByName = function(name)
|
||||
if not name or name == "" then return end
|
||||
if itemLinkByNameCache[name] then
|
||||
return itemLinkByNameCache[name]
|
||||
end
|
||||
|
||||
local ownedLink = FindOwnedItemLinkByName(name)
|
||||
if ownedLink then
|
||||
return CacheItemLink(name, ownedLink)
|
||||
end
|
||||
|
||||
-- Legacy compatibility fallback. Vanilla has no generic name -> itemID
|
||||
-- resolver, so retain the original base-game sweep for non-owned items.
|
||||
-- Crucially, custom items the player owns no longer depend on this limit.
|
||||
for itemID = 1, 25818 do
|
||||
local itemName, itemLink, itemQuality = GetItemInfo(itemID)
|
||||
if itemName and itemName == name then
|
||||
local _, _, _, hex = GetItemQualityColor(tonumber(itemQuality))
|
||||
local hyperLink = hex .. "|H" .. itemLink .. "|h[" .. itemName .. "]|h" .. FONT_COLOR_CODE_CLOSE
|
||||
return CacheItemLink(name, hyperLink)
|
||||
end
|
||||
end
|
||||
end
|
||||
'''
|
||||
helpers.write_text(head + tail, encoding='utf-8', newline='\n')
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# item-colors.lua: stop relying on parsed legacy links for bag/bank/
|
||||
# inspect rarity. Direct IDs + ClassicAPI quality work for Turtle IDs.
|
||||
# ------------------------------------------------------------------
|
||||
colors = Path('mods/item-colors.lua')
|
||||
text = colors.read_text(encoding='utf-8')
|
||||
|
||||
old = 'local T = ShaguTweaks.T\nlocal GetExpansion = ShaguTweaks.GetExpansion\n'
|
||||
new = 'local T = ShaguTweaks.T\nlocal API = ShaguTweaks.API\nlocal GetExpansion = ShaguTweaks.GetExpansion\n'
|
||||
if old not in text:
|
||||
raise SystemExit('item-colors.lua header marker not found')
|
||||
text = text.replace(old, new, 1)
|
||||
|
||||
old = 'local defcolor = {}\n\nlocal paperdoll_slots = {\n'
|
||||
new = r'''local defcolor = {}
|
||||
|
||||
local function GetQualityFromLink(link)
|
||||
if not link then return end
|
||||
local itemID = API and API.GetItemIDFromLink and API.GetItemIDFromLink(link)
|
||||
if itemID and API and API.GetItemQualityByID then
|
||||
local quality = API.GetItemQualityByID(itemID)
|
||||
if quality ~= nil then return quality end
|
||||
end
|
||||
|
||||
local _, _, istring = string.find(link, "|H(.+)|h")
|
||||
if istring then
|
||||
local _, _, quality = GetItemInfo(istring)
|
||||
return quality
|
||||
end
|
||||
end
|
||||
|
||||
local function GetBagItemQuality(bag, slot)
|
||||
if API and API.GetContainerItemID and API.GetItemQualityByID then
|
||||
local itemID = API.GetContainerItemID(bag, slot)
|
||||
if itemID then
|
||||
local quality = API.GetItemQualityByID(itemID)
|
||||
if quality ~= nil then return quality end
|
||||
end
|
||||
end
|
||||
|
||||
return GetQualityFromLink(GetContainerItemLink(bag, slot))
|
||||
end
|
||||
|
||||
local function GetUnitItemQuality(unit, slot)
|
||||
if API and API.GetInventoryItemID and API.GetItemQualityByID then
|
||||
local itemID = API.GetInventoryItemID(unit, slot)
|
||||
if itemID then
|
||||
local quality = API.GetItemQualityByID(itemID)
|
||||
if quality ~= nil then return quality end
|
||||
end
|
||||
end
|
||||
|
||||
return GetQualityFromLink(GetInventoryItemLink(unit, slot))
|
||||
end
|
||||
|
||||
local paperdoll_slots = {
|
||||
'''
|
||||
if old not in text:
|
||||
raise SystemExit('item-colors.lua helper marker not found')
|
||||
text = text.replace(old, new, 1)
|
||||
|
||||
old = ''' local link = GetInventoryItemLink("target", i)
|
||||
local border = button.ShaguTweaks_border
|
||||
'''
|
||||
new = ''' local quality = GetUnitItemQuality("target", i)
|
||||
local border = button.ShaguTweaks_border
|
||||
'''
|
||||
if old not in text:
|
||||
raise SystemExit('item-colors.lua inspect link marker not found')
|
||||
text = text.replace(old, new, 1)
|
||||
|
||||
old = ''' border:SetBackdropBorderColor(defcolor["inspect"][1], defcolor["inspect"][2], defcolor["inspect"][3], 1)
|
||||
if link then
|
||||
local _, _, istring = string.find(link, "|H(.+)|h")
|
||||
local _, _, quality = GetItemInfo(istring)
|
||||
if quality then
|
||||
local r, g, b = GetItemQualityColor(quality)
|
||||
border:SetBackdropBorderColor(r, g, b, 1)
|
||||
end
|
||||
end
|
||||
'''
|
||||
new = ''' border:SetBackdropBorderColor(defcolor["inspect"][1], defcolor["inspect"][2], defcolor["inspect"][3], 1)
|
||||
if quality ~= nil then
|
||||
local r, g, b = GetItemQualityColor(quality)
|
||||
border:SetBackdropBorderColor(r, g, b, 1)
|
||||
end
|
||||
'''
|
||||
if old not in text:
|
||||
raise SystemExit('item-colors.lua inspect quality marker not found')
|
||||
text = text.replace(old, new, 1)
|
||||
|
||||
old = ''' local link = GetContainerItemLink(id, button:GetID())
|
||||
if button and button:IsShown() and link then
|
||||
local _, _, istring = string.find(link, "|H(.+)|h")
|
||||
local _, _, quality = GetItemInfo(istring)
|
||||
if quality then
|
||||
local r, g, b = GetItemQualityColor(quality)
|
||||
button.ShaguTweaks_border:SetBackdropBorderColor(r,g,b)
|
||||
end
|
||||
end
|
||||
'''
|
||||
new = ''' local quality = GetBagItemQuality(id, button:GetID())
|
||||
if button and button:IsShown() and quality ~= nil then
|
||||
local r, g, b = GetItemQualityColor(quality)
|
||||
button.ShaguTweaks_border:SetBackdropBorderColor(r,g,b)
|
||||
end
|
||||
'''
|
||||
if old not in text:
|
||||
raise SystemExit('item-colors.lua bag quality marker not found')
|
||||
text = text.replace(old, new, 1)
|
||||
|
||||
old = ''' local button = _G["BankFrameItem"..i]
|
||||
\t\t local link = GetContainerItemLink(-1, i)
|
||||
if button then
|
||||
'''
|
||||
new = ''' local button = _G["BankFrameItem"..i]
|
||||
local quality = GetBagItemQuality(-1, i)
|
||||
if button then
|
||||
'''
|
||||
if old not in text:
|
||||
raise SystemExit('item-colors.lua bank link marker not found')
|
||||
text = text.replace(old, new, 1)
|
||||
|
||||
old = ''' if link then
|
||||
local _, _, istring = string.find(link, "|H(.+)|h")
|
||||
local _, _, q = GetItemInfo(istring)
|
||||
if q and q > 1 then
|
||||
local r, g, b = GetItemQualityColor(q)
|
||||
button.ShaguTweaks_border:SetBackdropBorderColor(r,g,b)
|
||||
end
|
||||
end
|
||||
'''
|
||||
new = ''' if quality and quality > 1 then
|
||||
local r, g, b = GetItemQualityColor(quality)
|
||||
button.ShaguTweaks_border:SetBackdropBorderColor(r,g,b)
|
||||
end
|
||||
'''
|
||||
if old not in text:
|
||||
raise SystemExit('item-colors.lua bank quality marker not found')
|
||||
text = text.replace(old, new, 1)
|
||||
|
||||
colors.write_text(text, encoding='utf-8', newline='\n')
|
||||
|
||||
# Sanity checks for the intended migration.
|
||||
assert 'API.GetContainerItemID = function' in api.read_text(encoding='utf-8')
|
||||
assert 'FindOwnedItemLinkByName' in helpers.read_text(encoding='utf-8')
|
||||
assert 'GetBagItemQuality' in colors.read_text(encoding='utf-8')
|
||||
print('ClassicAPI item foundation applied')
|
||||
|
||||
- name: Validate and commit
|
||||
run: |
|
||||
git diff --check
|
||||
git diff --stat
|
||||
git rm .github/workflows/item-api-foundation.yml
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git add api.lua helpers.lua mods/item-colors.lua
|
||||
git diff --cached --check
|
||||
git commit -m "Centralize ClassicAPI item handling"
|
||||
git push origin HEAD:classicapi-enhanced
|
||||
Reference in New Issue
Block a user