initial commit
This commit is contained in:
227
Core/Service/Crafting/Sync.lua
Normal file
227
Core/Service/Crafting/Sync.lua
Normal file
@@ -0,0 +1,227 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- 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
|
||||
Reference in New Issue
Block a user