Browse Source

channel sync?

dev
Jørgen Lien Sellæg 4 months ago
parent
commit
c6820172a9
  1. 191
      TradeSkillMaster_AuctionDB/Modules/ChannelSync.lua
  2. 6
      TradeSkillMaster_AuctionDB/Modules/Scanning.lua
  3. 3
      TradeSkillMaster_AuctionDB/Modules/data.lua
  4. 3
      TradeSkillMaster_AuctionDB/TradeSkillMaster_AuctionDB.toc

191
TradeSkillMaster_AuctionDB/Modules/ChannelSync.lua

@ -0,0 +1,191 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster_AuctionDB --
-- http://www.curse.com/addons/wow/tradeskillmaster_auctiondb --
-- --
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
-- All Rights Reserved* - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
-- Channel sync for sharing AuctionDB scan data between players.
local TSM = select(2, ...)
local ChannelSync = TSM:NewModule("ChannelSync", "AceComm-3.0", "AceEvent-3.0")
local CHANNEL_NAME = "TSM_AuctionDB"
local COMM_PREFIX = "TSMAuctionDB"
local CHUNK_SIZE = 220
local BUNDLE_TIMEOUT = 45
local private = {
channelId = nil,
lastBroadcastHash = nil,
incoming = {},
}
local strbyte = string.byte
local libS = LibStub:GetLibrary("AceSerializer-3.0")
local libC = LibStub:GetLibrary("LibCompress")
local libCE = libC:GetAddonEncodeTable()
local function HashString(str)
local hash = 0
for i = 1, #str do
hash = (hash * 31 + strbyte(str, i)) % 4294967296
end
return tostring(hash)
end
local function EnsureChannel()
local channelId = GetChannelName(CHANNEL_NAME)
if channelId == 0 then
JoinChannelByName(CHANNEL_NAME)
channelId = GetChannelName(CHANNEL_NAME)
end
private.channelId = channelId > 0 and channelId or nil
end
local function ChatFilter(_, _, msg, _, _, _, _, _, channelName)
if channelName ~= CHANNEL_NAME then return end
if strsub(msg, 1, #COMM_PREFIX) == COMM_PREFIX then
return true
end
end
function ChannelSync:OnEnable()
self:RegisterComm(COMM_PREFIX)
self:RegisterEvent("PLAYER_ENTERING_WORLD", "OnPlayerEnteringWorld")
self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE", "OnChannelNotice")
if ChatFrame_AddMessageEventFilter then
ChatFrame_AddMessageEventFilter("CHAT_MSG_CHANNEL", ChatFilter)
end
EnsureChannel()
end
function ChannelSync:OnPlayerEnteringWorld()
EnsureChannel()
end
function ChannelSync:OnChannelNotice()
EnsureChannel()
end
local function EncodePayload(payload)
local serialized = libS:Serialize(payload)
local encoded = libCE:Encode(libC:CompressHuffman(serialized))
if not encoded then
encoded = libCE:Encode(libC:CompressLZW(serialized))
end
if not encoded then
encoded = libCE:Encode("\001" .. serialized)
end
return encoded
end
local function DecodePayload(encoded)
local decoded = libCE:Decode(encoded)
if not decoded then return end
local decompressed = libC:Decompress(decoded)
if not decompressed then return end
local ok, payload = libS:Deserialize(decompressed)
if not ok then return end
return payload
end
function ChannelSync:BroadcastScanData(scanType)
if scanType ~= "Full" and scanType ~= "GetAll" and scanType ~= "Group" and scanType ~= "Search" then
return
end
if TSM.processingData then
TSMAPI:CreateTimeDelay("auctionDBChannelSyncBroadcast", 0.5, function()
ChannelSync:BroadcastScanData(scanType)
end)
return
end
EnsureChannel()
if not private.channelId then return end
TSM:Serialize()
local payload = {
scanTime = TSM.db.realm.lastCompleteScan,
scanData = TSM.db.realm.scanData,
}
local encoded = EncodePayload(payload)
if not encoded then return end
local hash = HashString(encoded)
if hash == private.lastBroadcastHash then return end
private.lastBroadcastHash = hash
local total = ceil(#encoded / CHUNK_SIZE)
for i = 1, total do
local chunk = strsub(encoded, (i - 1) * CHUNK_SIZE + 1, i * CHUNK_SIZE)
local msg = strjoin("|", COMM_PREFIX, hash, i .. "/" .. total, chunk)
self:SendCommMessage(COMM_PREFIX, msg, "CHANNEL", private.channelId)
end
end
local function MergeIncomingData(payload)
if type(payload) ~= "table" or type(payload.scanData) ~= "string" then return end
local incoming = {}
TSM:Deserialize(payload.scanData, incoming, true)
for itemID, data in pairs(incoming) do
local existing = TSM.data[itemID]
if existing then
TSM:DecodeItemData(itemID)
if data.lastScan and (not existing.lastScan or data.lastScan > existing.lastScan) then
TSM.data[itemID] = data
end
else
TSM.data[itemID] = data
end
end
if payload.scanTime and (not TSM.db.realm.lastCompleteScan or payload.scanTime > TSM.db.realm.lastCompleteScan) then
TSM.db.realm.lastCompleteScan = payload.scanTime
end
TSM:Serialize()
end
function ChannelSync:OnCommReceived(_, msg, _, source)
source = ("-"):split(source or "")
if strlower(source or "") == strlower(UnitName("player") or "") then return end
local header, hash, seqInfo, chunk = msg:match("^(.-)|([^|]+)|([^|]+)|(.+)$")
if header ~= COMM_PREFIX or not hash or not seqInfo or not chunk then return end
local seq, total = seqInfo:match("^(%d+)%/(%d+)$")
seq, total = tonumber(seq), tonumber(total)
if not seq or not total then return end
local bundle = private.incoming[hash]
if not bundle or (time() - bundle.time) > BUNDLE_TIMEOUT then
bundle = {time = time(), total = total, chunks = {}, received = 0}
private.incoming[hash] = bundle
end
if bundle.total ~= total then
private.incoming[hash] = {time = time(), total = total, chunks = {}, received = 0}
bundle = private.incoming[hash]
end
if not bundle.chunks[seq] then
bundle.chunks[seq] = chunk
bundle.received = bundle.received + 1
end
if bundle.received < bundle.total then return end
local parts = {}
for i = 1, bundle.total do
if not bundle.chunks[i] then return end
tinsert(parts, bundle.chunks[i])
end
private.incoming[hash] = nil
local payload = DecodePayload(table.concat(parts))
if not payload then return end
MergeIncomingData(payload)
end

6
TradeSkillMaster_AuctionDB/Modules/Scanning.lua

@ -337,6 +337,9 @@ function Scan.ProcessGetAllScan(self)
-- Process the collected "GetAll" auction data as a new "complete scan" with today's date.
TSM.db.realm.lastCompleteScan = time()
TSM.Data:ProcessData(data, nil, verifyNewAlgorithm)
if TSM.ChannelSync then
TSM.ChannelSync:BroadcastScanData("GetAll")
end
-- Show GUI progress while we're waiting for the processing.
-- NOTE: The status text will be set to "complete" elsewhere, automatically.
@ -576,6 +579,9 @@ function Scan:ProcessScanData(scanData)
-- Process the collected auction data.
TSM.Data:ProcessData(data, Scan.groupItems, verifyNewAlgorithm)
if TSM.ChannelSync then
TSM.ChannelSync:BroadcastScanData(Scan.isScanning)
end
end
function Scan:ProcessImportedData(auctionData)

3
TradeSkillMaster_AuctionDB/Modules/data.lua

@ -170,6 +170,9 @@ function Data:ProcessExternalScanData(scanData, groupItems, scanTime)
if not next(data) then return end
Data:ProcessData(data, groupSet, nil, scanTime or time(), true)
if TSM.ChannelSync then
TSM.ChannelSync:BroadcastScanData("Search")
end
end
--- Process a table of new market scan data.

3
TradeSkillMaster_AuctionDB/TradeSkillMaster_AuctionDB.toc

@ -25,6 +25,7 @@ Locale\ptBR.lua
TradeSkillMaster_AuctionDB.lua
AppData.lua
Modules\data.lua
Modules\ChannelSync.lua
Modules\Scanning.lua
Modules\GUI.lua
Modules\config.lua
Modules\config.lua

Loading…
Cancel
Save