diff --git a/.gitignore b/.gitignore index ef69003..bbff391 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,7 @@ ENV/ # IDE .idea/ +.idea/* .vscode/ *.swp *.swo @@ -85,3 +86,4 @@ htmlcov/ # Environment variables .env .env.local + diff --git a/AscensionExporter/AscensionExporter.toc b/AscensionExporter/AscensionExporter.toc index ea3dcac..920f99c 100644 --- a/AscensionExporter/AscensionExporter.toc +++ b/AscensionExporter/AscensionExporter.toc @@ -6,8 +6,8 @@ ## SavedVariables: AscensionExporterSaved, AscensionExporterConfig Core.lua -Util/Json.lua -UI/ExportFrame.lua -Collectors/Talents.lua -Collectors/Gear.lua -Collectors/Enchants.lua +Util\Json.lua +UI\ExportFrame.lua +Collectors\Talents.lua +Collectors\Gear.lua +Collectors\Enchants.lua diff --git a/AscensionExporter/Collectors/Enchants.lua b/AscensionExporter/Collectors/Enchants.lua index 9da2236..7eb81c2 100644 --- a/AscensionExporter/Collectors/Enchants.lua +++ b/AscensionExporter/Collectors/Enchants.lua @@ -1,5 +1,8 @@ -- AscensionExporter - Mystic Enchants collector (from equipped item tooltips) +-- Ensure global addon table exists even if load order varies +AscensionExporter = _G.AscensionExporter or {} +_G.AscensionExporter = AscensionExporter local AE = AscensionExporter local SLOT_NAMES = { @@ -57,3 +60,6 @@ function AE.CollectMysticEnchants() table.sort(active, function(a,b) return a.name < b.name end) return { perSlot = perSlot, active = active } end + +-- Mark module as loaded for debug visibility +AE._loadedEnchants = true diff --git a/AscensionExporter/Collectors/Gear.lua b/AscensionExporter/Collectors/Gear.lua index 1f1de51..e8ce943 100644 --- a/AscensionExporter/Collectors/Gear.lua +++ b/AscensionExporter/Collectors/Gear.lua @@ -1,5 +1,8 @@ -- AscensionExporter - Gear collector (equipped items only) +-- Ensure global addon table exists even if load order varies +AscensionExporter = _G.AscensionExporter or {} +_G.AscensionExporter = AscensionExporter local AE = AscensionExporter local SLOT_NAMES = { @@ -114,3 +117,6 @@ function AE.CollectGear() end return out end + +-- Mark module as loaded for debug visibility +AE._loadedGear = true diff --git a/AscensionExporter/Collectors/Talents.lua b/AscensionExporter/Collectors/Talents.lua index 09a4482..bf0d673 100644 --- a/AscensionExporter/Collectors/Talents.lua +++ b/AscensionExporter/Collectors/Talents.lua @@ -1,5 +1,8 @@ -- AscensionExporter - Talents collector (active spec only) +-- Ensure global addon table exists even if load order varies +AscensionExporter = _G.AscensionExporter or {} +_G.AscensionExporter = AscensionExporter local AE = AscensionExporter local function get_active_group() @@ -54,3 +57,6 @@ function AE.CollectTalents() return out end + +-- Mark module as loaded for debug visibility +AE._loadedTalents = true diff --git a/AscensionExporter/Core.lua b/AscensionExporter/Core.lua index 4f82086..094ef63 100644 --- a/AscensionExporter/Core.lua +++ b/AscensionExporter/Core.lua @@ -1,7 +1,7 @@ -- AscensionExporter - Core local ADDON_NAME = ... -local AE = {} -AscensionExporter = AE +AscensionExporter = AscensionExporter or {} +local AE = AscensionExporter -- SavedVariables defaults AscensionExporterConfig = AscensionExporterConfig or {} @@ -22,6 +22,15 @@ local function IsArray(t) return true end +-- normalize simple string args (trim + lower) +local function Norm(s) + if s == nil then return nil end + s = tostring(s):lower() + s = s:match("^%s*(.-)%s*$") or s + if s == "" then return nil end + return s +end + -- Shims for safety local function SafeCall(fn, ...) local ok, r = pcall(fn, ...) @@ -31,6 +40,7 @@ end -- Export assembly function AE:AssembleExport(which) + which = Norm(which) local nowIso = date("!%Y-%m-%dT%H:%M:%SZ") local version, build, buildDate, toc = GetBuildInfo() @@ -142,7 +152,8 @@ function AE:ShowExport(text, titleText) end function AE:Export(which) - local data = self:AssembleExport(which) + local normWhich = Norm(which) + local data = self:AssembleExport(normWhich) -- Prefer global encoder from Util/Json.lua; fallback to a tiny local encoder if missing local function tiny_json_encode(v) local tv = type(v) @@ -173,7 +184,7 @@ function AE:Export(which) local json = encoder(data) local title = "Ascension Export" - if which and which ~= "all" then title = title .. " - " .. which end + if normWhich and normWhich ~= "all" then title = title .. " - " .. normWhich end self:ShowExport(json, title .. " - Copy All (Ctrl+C)") if AscensionExporterConfig.enableSavedVariables then @@ -272,14 +283,14 @@ SlashCmdList["ASCX"] = function(msg) -- avoid referencing buttons that won't be present in the fallback window. local hasButtons = type(_G.AscensionExporter_ShowExportFrame) == "function" local prefix = hasButtons and "Use the buttons above or type:" or "Type one of the commands:" - local help = prefix .. "\n/ascx export all|talents|gear|enchants|mdgear\n/ascx sv on|off (SavedVariables is currently " .. (AscensionExporterConfig.enableSavedVariables and "ON" or "OFF") .. ")\n" + local help = prefix .. "\n/ascx export all|talents|gear|enchants|mdgear\n/ascx sv on|off (SavedVariables is currently " .. (AscensionExporterConfig.enableSavedVariables and "ON" or "OFF") .. ")\n/ascx debug (show collector status)\n" AE:ShowExport(help, "Ascension Export - Tools & Help") return end local cmd, rest = msg:match("^(%S+)%s*(.*)$") if cmd == "export" then - rest = rest ~= "" and rest or "all" + rest = Norm(rest) or "all" if rest == "mdgear" or rest == "md" then local md = AE:GenerateMarkdownGear() AE:ShowExport(md, "Ascension Export - Markdown Gear - Copy All (Ctrl+C)") @@ -289,6 +300,44 @@ SlashCmdList["ASCX"] = function(msg) DEFAULT_CHAT_FRAME:AddMessage("AscensionExporter: unknown export target '" .. tostring(rest) .. "'") end return + elseif cmd == "debug" then + local lines = {} + local function add(msg) + table.insert(lines, msg) + end + add("AscensionExporter debug:") + add(string.format("- AddOn: %s", tostring(ADDON_NAME))) + add(string.format("- UI available: %s", type(_G.AscensionExporter_ShowExportFrame) == "function" and "yes" or "no")) + add(string.format("- JSON encoder: %s", type(_G.AscensionExporter_Json_Encode) == "function" and "yes" or "no")) + add(string.format("- Modules loaded flags: talents=%s gear=%s enchants=%s", + tostring(AE._loadedTalents or false), tostring(AE._loadedGear or false), tostring(AE._loadedEnchants or false))) + -- Talents + if type(AE.CollectTalents) == "function" then + local t = SafeCall(AE.CollectTalents) or {} + local n = #(t.selected or {}) + add(string.format("Talents: OK, selected=%d", n)) + else + add("Talents: MISSING function") + end + -- Gear + if type(AE.CollectGear) == "function" then + local g = SafeCall(AE.CollectGear) or {} + local n = #(g.slots or {}) + add(string.format("Gear: OK, slots=%d", n)) + else + add("Gear: MISSING function") + end + -- Enchants + if type(AE.CollectMysticEnchants) == "function" then + local e = SafeCall(AE.CollectMysticEnchants) or {} + local nps = #(e.perSlot or {}) + local na = #(e.active or {}) + add(string.format("MysticEnchants: OK, perSlot=%d, active=%d", nps, na)) + else + add("MysticEnchants: MISSING function") + end + AE:ShowExport(table.concat(lines, "\n"), "Ascension Export - Debug") + return elseif cmd == "sv" then if rest == "on" then AscensionExporterConfig.enableSavedVariables = true @@ -305,12 +354,11 @@ SlashCmdList["ASCX"] = function(msg) end end --- Basic event binding (not strictly necessary for slash-only usage) +-- Basic event binding local f = CreateFrame("Frame") f:RegisterEvent("ADDON_LOADED") f:SetScript("OnEvent", function(_, event, addon) - if event == "ADDON_LOADED" and addon == ADDON_NAME then - -- init defaults if needed + if event == "ADDON_LOADED" and addon == "AscensionExporter" then AscensionExporterConfig.enableSavedVariables = AscensionExporterConfig.enableSavedVariables and true or false end end) diff --git a/scripts/install_addon_sub.sh b/scripts/install_addon_sub.sh new file mode 100755 index 0000000..b4646a4 --- /dev/null +++ b/scripts/install_addon_sub.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Installs/syncs the AscensionExporter addon into your WoW Ascension AddOns folder. +# Default target: /srv/add01/wow-ascension/Interface/AddOns +# Usage: +# scripts/install_addon_sub.sh [TARGET_ADDONS_DIR] +# Example: +# scripts/install_addon_sub.sh /srv/add01/wow-ascension/Interface/AddOns + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="${SCRIPT_DIR}/.." + +SRC="${REPO_ROOT}/AscensionExporter" +DEST_BASE="${1:-/srv/add01/wow-ascension/Interface/AddOns}" +DEST="${DEST_BASE}/AscensionExporter" + +if [[ ! -d "${SRC}" ]]; then + echo "ERROR: Source addon folder not found at: ${SRC}" >&2 + exit 1 +fi + +echo "Installing AscensionExporter from: ${SRC}" +echo "Target AddOns directory: ${DEST_BASE}" + +mkdir -p "${DEST_BASE}" + +if command -v rsync >/dev/null 2>&1; then + echo "Using rsync to copy files..." + rsync -a --delete "${SRC}/" "${DEST}/" +else + echo "rsync not found; using cp -a" + mkdir -p "${DEST}" + # Copy contents of SRC into DEST, preserving attributes + cp -a "${SRC}/." "${DEST}/" +fi + +echo "Done. Addon installed to: ${DEST}" +echo "If needed, enable it on the character select screen and type /reload in-game."