228 lines
8.3 KiB
Lua
228 lines
8.3 KiB
Lua
-- ------------------------------------------------------------------------------ --
|
|
-- TradeSkillMaster --
|
|
-- https://tradeskillmaster.com --
|
|
-- All Rights Reserved - Detailed license information included with addon. --
|
|
-- ------------------------------------------------------------------------------ --
|
|
|
|
local _, TSM = ...
|
|
local CraftingSync = TSM.Crafting:NewPackage("Sync")
|
|
local L = TSM.Include("Locale").GetTable()
|
|
local Delay = TSM.Include("Util.Delay")
|
|
local TempTable = TSM.Include("Util.TempTable")
|
|
local String = TSM.Include("Util.String")
|
|
local Log = TSM.Include("Util.Log")
|
|
local Theme = TSM.Include("Util.Theme")
|
|
local Sync = TSM.Include("Service.Sync")
|
|
local private = {
|
|
hashesTemp = {},
|
|
spellsTemp = {},
|
|
spellsProfessionLookupTemp = {},
|
|
spellInfoTemp = {
|
|
spellIds = {},
|
|
mats = {},
|
|
itemStrings = {},
|
|
names = {},
|
|
numResults = {},
|
|
hasCDs = {},
|
|
},
|
|
accountLookup = {},
|
|
accountStatus = {},
|
|
}
|
|
local RETRY_DELAY = 5
|
|
local PROFESSION_HASH_FIELDS = { "spellId", "itemString" }
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- Module Functions
|
|
-- ============================================================================
|
|
|
|
function CraftingSync.OnInitialize()
|
|
Sync.RegisterConnectionChangedCallback(private.ConnectionChangedHandler)
|
|
Sync.RegisterRPC("CRAFTING_GET_HASHES", private.RPCGetHashes)
|
|
Sync.RegisterRPC("CRAFTING_GET_SPELLS", private.RPCGetSpells)
|
|
Sync.RegisterRPC("CRAFTING_GET_SPELL_INFO", private.RPCGetSpellInfo)
|
|
end
|
|
|
|
function CraftingSync.GetStatus(account)
|
|
local status = private.accountStatus[account]
|
|
if not status then
|
|
return Theme.GetFeedbackColor("RED"):ColorText(L["Not Connected"])
|
|
elseif status == "UPDATING" or status == "RETRY" then
|
|
return Theme.GetFeedbackColor("YELLOW"):ColorText(L["Updating"])
|
|
elseif status == "SYNCED" then
|
|
return Theme.GetFeedbackColor("GREEN"):ColorText(L["Up to date"])
|
|
else
|
|
error("Invalid status: "..tostring(status))
|
|
end
|
|
end
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- RPC Functions and Result Handlers
|
|
-- ============================================================================
|
|
|
|
function private.RPCGetHashes()
|
|
wipe(private.hashesTemp)
|
|
local player = UnitName("player")
|
|
private.GetPlayerProfessionHashes(player, private.hashesTemp)
|
|
return player, private.hashesTemp
|
|
end
|
|
|
|
function private.RPCGetHashesResultHandler(player, data)
|
|
if not player or not private.accountLookup[player] then
|
|
-- request timed out, so try again
|
|
Log.Warn("Getting hashes timed out")
|
|
if private.accountLookup[player] then
|
|
private.accountStatus[private.accountLookup[player]] = "RETRY"
|
|
Delay.AfterTime(RETRY_DELAY, private.RetryGetHashesRPC)
|
|
end
|
|
return
|
|
end
|
|
local currentInfo = TempTable.Acquire()
|
|
private.GetPlayerProfessionHashes(player, currentInfo)
|
|
local requestProfessions = TempTable.Acquire()
|
|
for profession, hash in pairs(data) do
|
|
if hash == currentInfo[profession] then
|
|
Log.Info("%s data for %s already up to date", profession, player)
|
|
else
|
|
Log.Info("Need updated %s data from %s (%s, %s)", profession, player, hash, tostring(currentInfo[hash]))
|
|
requestProfessions[profession] = true
|
|
end
|
|
end
|
|
TempTable.Release(currentInfo)
|
|
if next(requestProfessions) then
|
|
private.accountStatus[private.accountLookup[player]] = "UPDATING"
|
|
Sync.CallRPC("CRAFTING_GET_SPELLS", player, private.RPCGetSpellsResultHandler, requestProfessions)
|
|
else
|
|
private.accountStatus[private.accountLookup[player]] = "SYNCED"
|
|
end
|
|
TempTable.Release(requestProfessions)
|
|
end
|
|
|
|
function private.RPCGetSpells(professions)
|
|
wipe(private.spellsProfessionLookupTemp)
|
|
wipe(private.spellsTemp)
|
|
local player = UnitName("player")
|
|
local query = TSM.Crafting.CreateRawCraftsQuery()
|
|
:Select("spellId", "profession")
|
|
:Custom(private.QueryProfessionFilter, professions)
|
|
:Custom(private.QueryPlayerFilter, player)
|
|
:OrderBy("spellId", true)
|
|
for _, spellId, profession in query:Iterator() do
|
|
private.spellsProfessionLookupTemp[spellId] = profession
|
|
tinsert(private.spellsTemp, spellId)
|
|
end
|
|
query:Release()
|
|
return player, private.spellsProfessionLookupTemp, private.spellsTemp
|
|
end
|
|
|
|
function private.RPCGetSpellsResultHandler(player, professionLookup, spells)
|
|
if not player or not private.accountLookup[player] then
|
|
-- request timed out, so try again from the start
|
|
Log.Warn("Getting spells timed out")
|
|
if private.accountLookup[player] then
|
|
private.accountStatus[private.accountLookup[player]] = "RETRY"
|
|
Delay.AfterTime(RETRY_DELAY, private.RetryGetHashesRPC)
|
|
end
|
|
return
|
|
end
|
|
|
|
for i = #spells, 1, -1 do
|
|
local spellId = spells[i]
|
|
if TSM.Crafting.HasSpellId(spellId) then
|
|
-- already have this spell so just make sure this player is added
|
|
TSM.Crafting.AddPlayer(spellId, player)
|
|
tremove(spells, i)
|
|
end
|
|
end
|
|
if #spells == 0 then
|
|
Log.Info("Spells up to date for %s", player)
|
|
private.accountStatus[private.accountLookup[player]] = "SYNCED"
|
|
else
|
|
Log.Info("Requesting %d spells from %s", #spells, player)
|
|
Sync.CallRPC("CRAFTING_GET_SPELL_INFO", player, private.RPCGetSpellInfoResultHandler, professionLookup, spells)
|
|
end
|
|
end
|
|
|
|
function private.RPCGetSpellInfo(professionLookup, spells)
|
|
for _, tbl in pairs(private.spellInfoTemp) do
|
|
wipe(tbl)
|
|
end
|
|
for i, spellId in ipairs(spells) do
|
|
private.spellInfoTemp.spellIds[i] = spellId
|
|
private.spellInfoTemp.mats[i] = TSM.db.factionrealm.internalData.crafts[spellId].mats
|
|
private.spellInfoTemp.itemStrings[i] = TSM.db.factionrealm.internalData.crafts[spellId].itemString
|
|
private.spellInfoTemp.names[i] = TSM.db.factionrealm.internalData.crafts[spellId].name
|
|
private.spellInfoTemp.numResults[i] = TSM.db.factionrealm.internalData.crafts[spellId].numResult
|
|
private.spellInfoTemp.hasCDs[i] = TSM.db.factionrealm.internalData.crafts[spellId].hasCD
|
|
end
|
|
Log.Info("Sent %d spells", #private.spellInfoTemp.spellIds)
|
|
return UnitName("player"), professionLookup, private.spellInfoTemp
|
|
end
|
|
|
|
function private.RPCGetSpellInfoResultHandler(player, professionLookup, spellInfo)
|
|
if not player or not professionLookup or not spellInfo or not private.accountLookup[player] then
|
|
-- request timed out, so try again from the start
|
|
Log.Warn("Getting spell info timed out")
|
|
if private.accountLookup[player] then
|
|
private.accountStatus[private.accountLookup[player]] = "RETRY"
|
|
Delay.AfterTime(RETRY_DELAY, private.RetryGetHashesRPC)
|
|
end
|
|
return
|
|
end
|
|
|
|
for i, spellId in ipairs(spellInfo.spellIds) do
|
|
TSM.Crafting.CreateOrUpdate(spellId, spellInfo.itemStrings[i], professionLookup[spellId], spellInfo.names[i], spellInfo.numResults[i], player, spellInfo.hasCDs[i] and true or false)
|
|
for itemString in pairs(spellInfo.mats[i]) do
|
|
TSM.db.factionrealm.internalData.mats[itemString] = TSM.db.factionrealm.internalData.mats[itemString] or {}
|
|
end
|
|
TSM.Crafting.SetMats(spellId, spellInfo.mats[i])
|
|
end
|
|
Log.Info("Added %d spells from %s", #spellInfo.spellIds, player)
|
|
private.accountStatus[private.accountLookup[player]] = "SYNCED"
|
|
end
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- Private Helper Functions
|
|
-- ============================================================================
|
|
|
|
function private.ConnectionChangedHandler(account, player, connected)
|
|
if connected then
|
|
private.accountLookup[player] = account
|
|
private.accountStatus[account] = "UPDATING"
|
|
-- issue a request for profession info
|
|
Sync.CallRPC("CRAFTING_GET_HASHES", player, private.RPCGetHashesResultHandler)
|
|
else
|
|
private.accountLookup[player] = nil
|
|
private.accountStatus[account] = nil
|
|
end
|
|
end
|
|
|
|
function private.RetryGetHashesRPC()
|
|
for player, account in pairs(private.accountLookup) do
|
|
if private.accountStatus[account] == "RETRY" then
|
|
Sync.CallRPC("CRAFTING_GET_HASHES", player, private.RPCGetHashesResultHandler)
|
|
end
|
|
end
|
|
end
|
|
|
|
function private.QueryProfessionFilter(row, professions)
|
|
return professions[row:GetField("profession")]
|
|
end
|
|
|
|
function private.QueryPlayerFilter(row, player)
|
|
return String.SeparatedContains(row:GetField("players"), ",", player)
|
|
end
|
|
|
|
function private.GetPlayerProfessionHashes(player, resultTbl)
|
|
local query = TSM.Crafting.CreateRawCraftsQuery()
|
|
:Custom(private.QueryPlayerFilter, player)
|
|
:OrderBy("spellId", true)
|
|
query:GroupedHash(PROFESSION_HASH_FIELDS, "profession", resultTbl)
|
|
query:Release()
|
|
end
|